Creating Asana tasks from Google Apps Script

2019-09-05 14:59发布

I am trying to create tasks in Asana using google apps scripts. I do manage to read (GET method) any kind of information from asana, but when I try to do a POST like creating a new task in a specific workspace and project, it creates the task but using default values ignoring json data that I pass.

this is the code I've been using:

function createTask (taskName, wsId, projectId, asigneeId) {
  var encoded = Utilities.base64Encode(asanaKey + ":");
  var options = {
        "method" : "POST",
        "headers" : {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": "Basic " + Utilities.base64Encode(asanaKey + ":")
        }, 
        "body" : {
          "data" : {
              "name" : "\"" + taskName + "\"" ,
              "asignee" : asigneeId,
              "projects" : [projectId],
              "workspace" : wsId
           } 
        }
    };
  try {
        var url = "https://app.asana.com/api/1.0/workspaces/" + wsId + "/tasks";
        var result = UrlFetchApp.fetch(url, options);
        var salida = result.getContentText();
      } 
   catch (e) {
        Logger.log(e);
        var salida = "";
      }
  finally {
      return salida;
  }
}

I've tried with data outside body, workspace outside data, i've changed the order but it always create tasks with default values. ¿any ideas? Thanks

3条回答
地球回转人心会变
2楼-- · 2019-09-05 15:19

I found two aspects that were causing the issue, though it took a great deal of trial and error and debug.

OPTIONS object format

I think the main issue is the format of the 'options' object. I think it needs to have the main elements "method": "headers": and "payload": and not the "body" and "data" elements.

Authoriziation The authorisation aspect took me ages to figure out. for small apps like this use the Personal Access Token method. the important thing is to use the Authorization option in the header with the parameter of "Bearer " + PERSONAL_ACCESS_TOKEN

The PERSONAL_ACCESS_TOKEN is exactly the string as given to you in the Asana Web app at the time of registering a Personal Access Token. it DOES NOT need any further authorisation / exchanges / OAuths /refreshes, nor does it need any encoding in base 64 or any colons.

Debugging

I used Postman (https://www.getpostman.com/) and the explorer in the asana developers API reference to test out how the options worked, particularly around the authorisation.

I also setup a dummy function to create a defined name task so I could access the debugger in the google script editor.

CODE: Note I have adjusted the ids etc. so you have to put your own in.

/*************************
 * Asana     Functions    *
 *************************/

// first Global constants ... Key Ids / tokens etc.
PERSONAL_ACCESS_TOKEN = "0/d3c41c435b0c3f70b399999952edee5";  // Put your unique Personal access token here
WORKSPACE_ID = "49489999934875"; // Put in the main workspace key you want to access (you can copy from asana web address)
ASSIGNEE = "jondoe@nomail.com";  // put in the e-mail addresss you use to log into asana


// ** testTask() **  is useful for using as a Debug start point.  "select function" on script editor menu
// choose "testTask" then debug functionality is enabled

function testTask() {
    quickTask("a quick task")  
};


// ** quickTask(taskName) ** Made a short function so I could just add simple tasks easily
function quickTask(taskName) {
    var newTask = {
    name: taskName,
    workspace: WORKSPACE_ID,
    project: "",       // if you have a project you like to add add it here
    assignee: "me"     // Me is understood by asana
  };
  createAsanaTask(newTask);

};

/******************************************************************************************
 **  createAsanaTask(task) **
 ************************ 
 * creates a new asana task with information (like task name, project, notes etc.) contained in  
 * the  object 'newTask" passed to it.
 * 'task' should be of the format an object with option pairs that match the Asana task
 * key parameters, as many or as few as you want.
 * e.g. 
 * var newTask = {
 *   name: taskName,
 *   workspace: WORKSPACE_ID,
 *   project: "My Project",       // if you have a project you like to add add it here
 *   assignee: "JohnDoe@madeupmail.com"     // person the task should be assigned to.
 * }
 *  you could add other info like due dates etc.
 * it returns a "task" object containing all asana task elements of the one task created including the id.
 *************************************************************************************************/   



function createAsanaTask(task) {

    // when creating an Asana task you must have at least a workspace id and an assignee
    // this routine checks if you defined one in the argument you passed
if (task.workspace == null) {
    task.workspace=WORKSPACE_ID
    }
if (task.assignee == null) {
    task.assignee="me";
    }

 /* first setup  the "options" object with the following key elements:
 *
 *   method: can be GET,POST typically
 *
 *   headers: object containing header option pairs
 *                    "Accept": "application/json",        // accept JSON format
*                    "Content-Type": "application/json",  //content I'm passing is JSON format
*                    "Authorization": "Bearer " + PERSONAL_ACCESS_TOKEN // authorisation
*  the authorisation aspect took me ages to figure out.
*  for small apps like this use the Personal Access Token method.
*  the important thing is to use the Authorization option in the header with the 
*  parameter of  "Bearer " + PERSONAL_ACCESS_TOKEN
*  the PERSONAL_ACCESS_TOKEN  is exactly the string as given to you in the Asana Web app at
*  the time of registering a Personal Access Token.  it DOES NOT need any further authorisation / exchanges
*  NOR does it needo any encoding in base 64 or any colon.
*
*  payload: this can be an object with option pairs  required for each element to be created... in this case 
*           its the task elements as passed to this function in the argument "task" object.
*            I found it doesn't need stringifying or anything.   
*
       ********************************************************************************************************/      

var options = {
    "method": "POST",
    "headers": {
        "Accept": "application/json",
        "Content-Type": "application/json",
        "Authorization": "Bearer " + PERSONAL_ACCESS_TOKEN
               },
        "payload": task
        };
  // using try to capture errors 
try {
                          // set the base url to appropriate endpoint - 
                          // this case is "https://app.asana.com/api/1.0"  plus "/tasks"
                          // note workspace id or project id not in base url as they are in the payload options
                          // use asana API reference for the requirements for each method
var url = "https://app.asana.com/api/1.0/tasks";
                          // using url of endpoint and options object do a urlfetch.
                          // this returns an object that contains JSON data structure into the 'result' variable 
                          // see below for sample structure
var result = UrlFetchApp.fetch(url, options);
                          // 
var taskJSON = result.getContentText();
} catch (e) {
        Logger.log(e);
        return null;
} finally {
 // parse the result text with JSON format to get object, then get the "data" element from that object and return it.
 // this will be an object containing all the elements of the task.
    return JSON.parse(taskJSON).data;
    }
};
查看更多
我想做一个坏孩纸
3楼-- · 2019-09-05 15:23

I had a few troubles doing what you are trying to do and couldn't get the other codes posted here to work, but i finally figured it out. Can't exactly remember what i changed, but you can easily use this function to create a task and get its id:

CODE:

function testTask(){
  var taskName = "Test Task 2"; //Task Name
  var wsId = "44492991234567"; //Workspace ID
  var projectId = "9120451234567"; //Project ID
  var assigneeId = "44645081234567"; //Assignee ID
  var parentId = null; //Parent ID, can be null if no parent
  createTask(taskName, wsId, projectId, assigneeId, parentId);
}

function createTask (taskName, wsId, projectId, assigneeId, parentId) {
  var token = “access token goes here"; //your asana Personal Access Token
  var bearerToken = "Bearer " + token;
  var task = {
    data: {
      assignee : 'me',
      notes : 'test', 
      workspace: wsId,
      name : taskName,
      projects : [projectId],
      parent: parentId
    }
  };
  var options = {
    "method" : "POST",
    "headers" : {"Authorization": bearerToken}, 
    "contentType": 'application/json',
    "payload" : JSON.stringify(task) 
  };
  try {
    var url = "https://app.asana.com/api/1.0/tasks";
    var result = UrlFetchApp.fetch(url, options);
    var reqReturn = result.getContentText();
    Logger.log(reqReturn);
    var createdTaskId = JSON.stringify(JSON.parse(reqReturn).data.id);
    Logger.log(createdTaskId);
  } 
  catch (e) {
    Logger.log(e);
  }
  return createdTaskId;
}
查看更多
一纸荒年 Trace。
4楼-- · 2019-09-05 15:44

Try stringifying your body, also, google uses the method payload, dunno if this is applicable with all REST requests:

var options = {
        "method" : "POST",
        "headers" : {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": "Basic " + Utilities.base64Encode(asanaKey + ":")
        }
     }
var body = {
          "data" : {
              "name" : "\"" + taskName + "\"" ,
              "asignee" : asigneeId,
              "projects" : [projectId],
              "workspace" : wsId
           } 
        };
options.payload = JSON.stringify(body);

Was gonna post as a comment, but code is unreadeable there.

查看更多
登录 后发表回答