github.com/wtfutil/wtf@v0.43.0/modules/asana/client.go (about)

     1  package asana
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	asana "bitbucket.org/mikehouston/asana-go"
     9  )
    10  
    11  func fetchTasksFromProject(token, projectId, mode string) ([]*TaskItem, error) {
    12  	taskItems := []*TaskItem{}
    13  	uidToName := make(map[string]string)
    14  
    15  	client := asana.NewClientWithAccessToken(token)
    16  
    17  	uid, err := getCurrentUserId(client, mode)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	q := &asana.TaskQuery{
    23  		Project: projectId,
    24  	}
    25  
    26  	fetchedTasks, _, err := getTasksFromAsana(client, q)
    27  	if err != nil {
    28  		return nil, fmt.Errorf("error fetching tasks: %s", err)
    29  	}
    30  
    31  	processFetchedTasks(client, &fetchedTasks, &taskItems, &uidToName, mode, projectId, uid)
    32  
    33  	return taskItems, nil
    34  }
    35  
    36  func fetchTasksFromProjectSections(token, projectId string, sections []string, mode string) ([]*TaskItem, error) {
    37  	taskItems := []*TaskItem{}
    38  	uidToName := make(map[string]string)
    39  
    40  	client := asana.NewClientWithAccessToken(token)
    41  
    42  	uid, err := getCurrentUserId(client, mode)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	p := &asana.Project{
    48  		ID: projectId,
    49  	}
    50  
    51  	for _, section := range sections {
    52  
    53  		sectionId, err := findSection(client, p, section)
    54  		if err != nil {
    55  			return nil, fmt.Errorf("error fetching tasks: %s", err)
    56  		}
    57  
    58  		q := &asana.TaskQuery{
    59  			Section: sectionId,
    60  		}
    61  
    62  		fetchedTasks, _, err := getTasksFromAsana(client, q)
    63  		if err != nil {
    64  			return nil, fmt.Errorf("error fetching tasks: %s", err)
    65  		}
    66  
    67  		if len(fetchedTasks) > 0 {
    68  			taskItem := &TaskItem{
    69  				name:     section,
    70  				taskType: TASK_SECTION,
    71  			}
    72  
    73  			taskItems = append(taskItems, taskItem)
    74  		}
    75  
    76  		processFetchedTasks(client, &fetchedTasks, &taskItems, &uidToName, mode, projectId, uid)
    77  
    78  	}
    79  
    80  	return taskItems, nil
    81  }
    82  
    83  func fetchTasksFromWorkspace(token, workspaceId, mode string) ([]*TaskItem, error) {
    84  	taskItems := []*TaskItem{}
    85  	uidToName := make(map[string]string)
    86  
    87  	client := asana.NewClientWithAccessToken(token)
    88  
    89  	uid, err := getCurrentUserId(client, mode)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	q := &asana.TaskQuery{
    95  		Workspace: workspaceId,
    96  		Assignee:  "me",
    97  	}
    98  
    99  	fetchedTasks, _, err := getTasksFromAsana(client, q)
   100  	if err != nil {
   101  		return nil, fmt.Errorf("error fetching tasks: %s", err)
   102  	}
   103  
   104  	processFetchedTasks(client, &fetchedTasks, &taskItems, &uidToName, mode, workspaceId, uid)
   105  
   106  	return taskItems, nil
   107  
   108  }
   109  
   110  func toggleTaskCompletionById(token, taskId string) error {
   111  	client := asana.NewClientWithAccessToken(token)
   112  
   113  	t := &asana.Task{
   114  		ID: taskId,
   115  	}
   116  
   117  	err := t.Fetch(client)
   118  	if err != nil {
   119  		return fmt.Errorf("error fetching task: %s", err)
   120  	}
   121  
   122  	updateReq := &asana.UpdateTaskRequest{}
   123  
   124  	if *t.Completed {
   125  		f := false
   126  		updateReq.Completed = &f
   127  	} else {
   128  		t := true
   129  		updateReq.Completed = &t
   130  	}
   131  
   132  	err = t.Update(client, updateReq)
   133  	if err != nil {
   134  		return fmt.Errorf("error updating task: %s", err)
   135  	}
   136  
   137  	return nil
   138  }
   139  
   140  func processFetchedTasks(client *asana.Client, fetchedTasks *[]*asana.Task, taskItems *[]*TaskItem, uidToName *map[string]string, mode, projectId, uid string) {
   141  
   142  	for _, task := range *fetchedTasks {
   143  		switch {
   144  		case strings.HasSuffix(mode, "_all"):
   145  			if task.Assignee != nil {
   146  				// Check if we have already looked up this user
   147  				if assigneeName, ok := (*uidToName)[task.Assignee.ID]; ok {
   148  					task.Assignee.Name = assigneeName
   149  				} else {
   150  					// We haven't looked up this user before, perform the lookup now
   151  					assigneeName, err := getOtherUserEmail(client, task.Assignee.ID)
   152  					if err != nil {
   153  						task.Assignee.Name = "Error"
   154  					}
   155  					(*uidToName)[task.Assignee.ID] = assigneeName
   156  					task.Assignee.Name = assigneeName
   157  				}
   158  			} else {
   159  				task.Assignee = &asana.User{
   160  					Name: "Unassigned",
   161  				}
   162  			}
   163  			taskItem := buildTaskItem(task, projectId)
   164  			(*taskItems) = append((*taskItems), taskItem)
   165  		case !strings.HasSuffix(mode, "_all") && task.Assignee != nil && task.Assignee.ID == uid:
   166  			taskItem := buildTaskItem(task, projectId)
   167  			(*taskItems) = append((*taskItems), taskItem)
   168  		}
   169  	}
   170  }
   171  
   172  func buildTaskItem(task *asana.Task, projectId string) *TaskItem {
   173  	dueOnString := ""
   174  	if task.DueOn != nil {
   175  		dueOn := time.Time(*task.DueOn)
   176  		currentYear, _, _ := time.Now().Date()
   177  		if currentYear != dueOn.Year() {
   178  			dueOnString = dueOn.Format("Jan 2 2006")
   179  		} else {
   180  			dueOnString = dueOn.Format("Jan 2")
   181  		}
   182  	}
   183  
   184  	assignString := ""
   185  	if task.Assignee != nil {
   186  		assignString = task.Assignee.Name
   187  	}
   188  
   189  	taskItem := &TaskItem{
   190  		name:        task.Name,
   191  		id:          task.ID,
   192  		numSubtasks: task.NumSubtasks,
   193  		dueOn:       dueOnString,
   194  		url:         fmt.Sprintf("https://app.asana.com/0/%s/%s/f", projectId, task.ID),
   195  		taskType:    TASK_TYPE,
   196  		completed:   *task.Completed,
   197  		assignee:    assignString,
   198  	}
   199  
   200  	return taskItem
   201  
   202  }
   203  
   204  func getOtherUserEmail(client *asana.Client, uid string) (string, error) {
   205  	if uid == "" {
   206  		return "", fmt.Errorf("missing uid")
   207  	}
   208  
   209  	u := &asana.User{
   210  		ID: uid,
   211  	}
   212  
   213  	err := u.Fetch(client, nil)
   214  	if err != nil {
   215  		return "", fmt.Errorf("error fetching user: %s", err)
   216  	}
   217  
   218  	return u.Email, nil
   219  }
   220  
   221  func getCurrentUserId(client *asana.Client, mode string) (string, error) {
   222  	if strings.HasSuffix(mode, "_all") {
   223  		return "", nil
   224  	}
   225  	u, err := client.CurrentUser()
   226  	if err != nil {
   227  		return "", fmt.Errorf("error getting current user: %s", err)
   228  	}
   229  
   230  	return u.ID, nil
   231  }
   232  
   233  func findSection(client *asana.Client, project *asana.Project, sectionName string) (string, error) {
   234  	sectionId := ""
   235  
   236  	sections, _, err := project.Sections(client, &asana.Options{
   237  		Limit: 100,
   238  	})
   239  	if err != nil {
   240  		return "", fmt.Errorf("error getting sections: %s", err)
   241  	}
   242  
   243  	for _, section := range sections {
   244  		if section.Name == sectionName {
   245  			sectionId = section.ID
   246  			break
   247  		}
   248  	}
   249  
   250  	if sectionId == "" {
   251  		return "", fmt.Errorf("we didn't find the section %s", sectionName)
   252  	}
   253  
   254  	return sectionId, nil
   255  }
   256  
   257  func getTasksFromAsana(client *asana.Client, q *asana.TaskQuery) ([]*asana.Task, bool, error) {
   258  	moreTasks := false
   259  
   260  	tasks, np, err := client.QueryTasks(q, &asana.Options{
   261  		Limit: 100,
   262  		Fields: []string{
   263  			"assignee",
   264  			"name",
   265  			"num_subtasks",
   266  			"due_on",
   267  			"completed",
   268  		},
   269  	})
   270  
   271  	if err != nil {
   272  		return nil, false, fmt.Errorf("error querying tasks: %s", err)
   273  	}
   274  
   275  	if np != nil {
   276  		moreTasks = true
   277  	}
   278  
   279  	return tasks, moreTasks, nil
   280  }