From ae132c2484199cb193028c831ea310688ac9f199 Mon Sep 17 00:00:00 2001 From: Aerex Date: Sat, 22 Dec 2018 01:07:43 -0600 Subject: [PATCH] feat: added user_assigned_to uda and fixed merge into tw method --- sample.config.yml | 6 +- twservices/apps/__init__.py | 6 +- twservices/apps/grocy.py | 114 +++++++++++++++++++++++++++++++----- 3 files changed, 106 insertions(+), 20 deletions(-) diff --git a/sample.config.yml b/sample.config.yml index a9b24ea..e579b65 100644 --- a/sample.config.yml +++ b/sample.config.yml @@ -7,7 +7,7 @@ services: - name: grocy api: 'https://aerex.me/grocy/api' token: 'McaeCf5FrT9Sqr96tPcZg9l4uUCexR1fGVGIfDR6qNQxsWECpv' - resolution: tw - tags: - - grocy + resolution: grocy + category: grocy + assigned_to: grocy diff --git a/twservices/apps/__init__.py b/twservices/apps/__init__.py index 73306ff..3152112 100644 --- a/twservices/apps/__init__.py +++ b/twservices/apps/__init__.py @@ -21,13 +21,17 @@ class RestService(object): self.headers = {} self.json = json - def get(self, path): + def get(self, path, id=None): + # TODO: change this to a single pattern assume a pattern then stick with it if self.api_url.endswith('/'): url = '{0}{1}'.format(self.api_url, path[1:]) else: url = '{0}{1}'.format(self.api_url, path) + if id: + url = '{0}/{1}'.format(url, id) + r = requests.get(url, headers=self.headers) if r.raise_for_status(): diff --git a/twservices/apps/grocy.py b/twservices/apps/grocy.py index 68c9597..33dc6af 100644 --- a/twservices/apps/grocy.py +++ b/twservices/apps/grocy.py @@ -12,15 +12,28 @@ class Grocy(TaskService): # Endpoints FIND_ALL_TASKS_ENDPOINT = '/get-objects/tasks' + FIND_ALL_CATEGORIES_ENDPOINT = '/get-objects/task_categories' DELETE_TASK_ENDPOINT = '/delete-object/tasks/{0}' + ADD_CATEGORY_ENDPOINT = '/add-object/task_categories' ADD_TASK_ENDPOINT = '/add-object/tasks' MODIFY_TASK_ENDPOINT = '/edit-object/tasks' # UDA GROCY_ID = 'grocy_id' + GROCY_ASSIGNED_TO_USER_ID = 'grocy_assigned_to' + GROCY_CATEGORY_ID = 'grocy_category_id' + GROCY_CATEGORY_NAME = 'grocy_category_name' UDAS = { GROCY_ID: { 'type': 'string', 'label': 'Grocy Task ID' + }, + GROCY_ASSIGNED_TO_USER_ID: { + 'type': 'string', + 'label': 'Grocy Assigned User ID' + }, + GROCY_CATEGORY_ID: { + 'type': 'string', + 'label': 'Grocy Category ID' } } @@ -50,17 +63,62 @@ class Grocy(TaskService): return tasks + def get_category(self): + if not self.rest_service: + raise Exception('rest service for grocy is not defined') + # Find specified category from all categories + try: + responses = self.rest_service.get(Grocy.FIND_ALL_CATEGORIES_ENDPOINT) + except BaseException as e: + logger.error(e) + raise e + + if responses: + for category in responses: + if category['name'] == self.category: + print('not sure') + print(category) + return category + logger.warn('Could not find category {} in list'.format(self.category)) + + return None + + def create_category(self): + if not self.rest_service: + raise Exception('rest service for grocy is not defined') + # Add new category to list + try: + responses = self.rest_service.get(Grocy.ADD_CATEGORY_ENDPOINT, self.category) + except BaseException as e: + logger.error(e) + raise e + + return responses + def to_grocy(self, task): - print('before the dawn') - print(task) grocy_task = {} if Grocy.GROCY_ID in task: grocy_task['id'] = task[Grocy.GROCY_ID] + if 'uuid' in task: + grocy_task['_uuid'] = task['uuid'] + + if Grocy.GROCY_ASSIGNED_TO_USER_ID in task: + grocy_task['assigned_to_user_id'] = task[Grocy.GROCY_ASSIGNED_TO_USER_ID] + if 'description' in task: grocy_task['name'] = task['description'] + if 'tags' in task and self.category in task['tags']: + category_id = self.get_category() + category_does_not_exist = not category_id + + if category_does_not_exist: + category_id = self.create_category() + + grocy_task['category'] = category_id + if 'annotations' in task: grocy_task['description'] = '' for note in task['annotations']: @@ -82,16 +140,24 @@ class Grocy(TaskService): if 'id' in grocy_task: taskwarrior_task[Grocy.GROCY_ID] = grocy_task['id'] + if '_uuid' in grocy_task: + taskwarrior_task['uuid'] = grocy_task['_uuid'] + + if 'assigned_to_user_id' in grocy_task: + taskwarrior_task[Grocy.GROCY_ASSIGNED_TO_USER_ID] = grocy_task['assigned_to_user_id'] if 'name' in grocy_task: taskwarrior_task['description'] = grocy_task['name'] if 'description' in grocy_task: + if '\r' in grocy_task['description']: + grocy_task['description'] = grocy_task['description'].replace('\r', '') taskwarrior_task['annotations'] = grocy_task['description'].split('\n') last_element_is_empty_string = taskwarrior_task['annotations'][-1] == '' if last_element_is_empty_string: taskwarrior_task['annotations'] = taskwarrior_task['annotations'][0:-1] # Remove empty string in array + if 'row_created_timestamp' in grocy_task: taskwarrior_task['entry'] = grocy_task['row_created_timestamp'] @@ -101,8 +167,12 @@ class Grocy(TaskService): if 'done' in grocy_task and grocy_task['done'] == '1': taskwarrior_task['status'] = 'completed' - return taskwarrior_task + if 'category_id' in grocy_task: + category = self.get_category() + taskwarrior_task[Grocy.GRO + + return taskwarrior_task def __initRestService(self): if self.api.startswith == '/': @@ -219,7 +289,7 @@ class Grocy(TaskService): # Delete taskwarrior task if self._should_merge(converted_tw_to_grocy_task, grocy_task): modified_grocy_tasks.append(converted_tw_to_grocy_task) - logger.debug('Merged taskwarrior task %s to grocy task %s', converted_tw_to_grocy_task['uuid'], grocy_task['id']) + logger.debug('Merged taskwarrior task %s to grocy task %s', converted_tw_to_grocy_task['id'], grocy_task['id']) del remaining_grocy_tasks_to_process[index] # Add taskwarrior task into taskwarrior else: @@ -230,19 +300,33 @@ class Grocy(TaskService): # Send requests to Grocy service if len(modified_grocy_tasks) > 0: modify_responses = self.modify(modified_grocy_tasks) - logger.debug(added_responses) + logger.debug(modify_responses) if len(tasks_to_add_to_grocy) > 0: added_responses = self.add(tasks_to_add_to_grocy) logger.debug(added_responses) def merge_into_tw(self, taskwarrior_tasks, grocy_tasks): + print(taskwarrior_tasks) + print(grocy_tasks) # Convert to taskwarrior tasks into grocy tasks converted_tw_to_grocy_tasks = [] converted_tw_to_grocy_tasks = [self.to_grocy(task) for task in taskwarrior_tasks] # Sort grocy tasks by id and converted taskwarrior tasks by GROCY_ID grocy_tasks.sort(key=lambda x: x['id']) - converted_tw_to_grocy_tasks.sort(key=lambda x: x[Grocy.GROCY_ID]) + converted_tw_to_grocy_tasks.sort(key=lambda x: x['id']) + + # If no taskwarrior tasks add grocy tasks to taskwarrior + if len(converted_tw_to_grocy_tasks) == 0: + convert_grocy_tasks_to_tw = [self.to_taskwarrior(grocy_task) for grocy_task in grocy_tasks] + for task in convert_grocy_tasks_to_tw: + try: + added_task = self.tw.task_add(**task) + logger.debug('Added grocy task %s to taskwarrior', task) + except TaskwarriorError as e: + logger.exception('Unable to add task from grocy: %s', e.stderr) + return + if len(grocy_tasks) == 0: self.add(converted_tw_to_grocy_tasks) @@ -263,21 +347,17 @@ class Grocy(TaskService): continue # Merge from grocy into taskwarrior if match found # Delete taskwarrior task - if self.should_merge(converted_tw_to_grocy_task, grocy_task): + if self._should_merge(converted_tw_to_grocy_task, grocy_task): try: converted_grocy_task_to_tw = self.to_taskwarrior(grocy_task) - self.tw.update(converted_grocy_task_to_tw) + converted_grocy_task_to_tw['uuid'] = converted_tw_to_grocy_task['_uuid'] + print('convert fool') + print(converted_grocy_task_to_tw) + self.tw.task_update(converted_grocy_task_to_tw) logger.debug('Merged grocy task %s to taskwarrior task %s', grocy_task['id'], converted_grocy_task_to_tw['uuid']) del converted_tw_to_grocy_tasks[index] except TaskwarriorError as e: logger.exception('Could not update task: %s', e.stderr) - # Add grocy task into taskwarrior - else: - try: - self.tw.task_add(converted_grocy_task_to_tw) - logger.debug('Added grocy task %s to taskwarrior task', grocy_task['id']) - except TaskwarriorError as e: - logger.exception('Could not add task: %s', e.stderr) def sync(self): @@ -295,7 +375,9 @@ class Grocy(TaskService): try: if self.resolution == 'tw': self.merge_from_tw(taskwarrior_tasks, grocy_tasks) - else: + elif self.resolution == 'grocy': self.merge_into_tw(taskwarrior_tasks, grocy_tasks) + else: + raise Exception('Could not determine resolution for grocy') except TaskwarriorError as e: logger.exception('Could not sync tasks %s', e.stderr)