Skip to content

Instantly share code, notes, and snippets.

@yuhki50
Created November 14, 2018 02:46
Show Gist options
  • Save yuhki50/15a9212b28ecd77f24b44e09253c35b6 to your computer and use it in GitHub Desktop.
Save yuhki50/15a9212b28ecd77f24b44e09253c35b6 to your computer and use it in GitHub Desktop.
export-wrike.py
#!/usr/bin/env python
from pathlib import Path
from pprint import pprint
import json
import requests
class Wrike:
ENDPOINT = 'https://www.wrike.com/api/v4'
API_KEY = 'YOUR API KEY'
@classmethod
def _request_wrike(cls, path, params=None):
path = Path(path)
local_file_path = path.with_suffix('.json')
if local_file_path.exists():
return json.loads(local_file_path.read_text())
else:
url = f'{cls.ENDPOINT}/{path}'
r = requests.get(url,
headers={'Authorization': f'bearer {cls.API_KEY}'},
params=params)
if r.status_code != requests.codes.ok:
print(r.status_code)
raise Exception(f'failed request {r.url} {r.status_code} {r.text}')
pprint(r.url)
pprint(r.text)
path.parent.mkdir(parents=True, exist_ok=True)
local_file_path.write_text(r.text)
return json.loads(r.text)
@classmethod
def _in_fields(cls, field, fields):
return fields and field in fields
@classmethod
def get_projects(cls, with_fields=None):
projects = cls._request_wrike('folders')['data']
if cls._in_fields('tasks', with_fields):
for project in projects:
project['tasks'] = cls.get_task_tree(project['id'], with_fields)
return list(filter(lambda v: not v['scope'].startswith('Rb'), projects))
@classmethod
def get_project_tree(cls, with_fields=None):
projects = cls.get_projects(with_fields)
root_project = list(filter(lambda v: v['scope'] == 'WsRoot', projects))
if len(root_project) > 1:
raise Exception('WsRoot is many')
root_project = root_project[0]
cls._merge_child_projects(root_project, projects)
return root_project
@classmethod
def print_project_tree(cls, project, shift=0, with_fields=None):
space = ' ' * shift
print(f"{space}> {project['title']} : {project['id']}")
if cls._in_fields('tasks', with_fields) and 'tasks' in project:
cls.print_tasks(project['tasks'], shift + 1, with_fields)
if 'childProjects' in project:
for p in project['childProjects']:
cls.print_project_tree(p, shift + 2, with_fields)
@classmethod
def _merge_child_projects(cls, project, projects):
for child_id in project['childIds']:
for p in projects:
if p['id'] == child_id:
if 'childProjects' not in project:
project['childProjects'] = []
cls._merge_child_projects(p, projects)
project['childProjects'].append(p)
@classmethod
def get_tasks(cls, project_id, with_fields=None):
tasks = cls._request_wrike(f'folders/{project_id}/tasks', params={
'subTasks': True,
'fields': json.dumps([
'description',
'superTaskIds',
'subTaskIds',
'dependencyIds',
]),
})['data']
if cls._in_fields('comments', with_fields):
for task in tasks:
task['comments'] = cls.get_comments(task['id'])
return tasks
@classmethod
def get_task_tree(cls, project_id, with_fields=None):
tasks = cls.get_tasks(project_id, with_fields)
for task in tasks:
cls._merge_sub_tasks(task, tasks)
return tasks
@classmethod
def print_tasks(cls, tasks, shift=0, with_fields=None):
space = ' ' * shift
for task in tasks:
print(f"{space}* {task['title']} : {task['id']}")
if cls._in_fields('comments', with_fields) and 'comments' in task:
cls.print_comments(task['comments'], shift + 1)
if 'subTasks' in task:
cls.print_tasks(task['subTasks'], shift + 2, with_fields)
@classmethod
def _merge_sub_tasks(cls, task, tasks):
task['subTasks'] = []
for sub_task_id in task['subTaskIds']:
for t in tasks:
if t['id'] == sub_task_id:
cls._merge_sub_tasks(t, tasks)
task['subTasks'].append(t)
tasks.remove(t)
@classmethod
def get_comments(cls, task_id):
return cls._request_wrike(f'tasks/{task_id}/comments')['data']
@classmethod
def print_comments(cls, comments, shift=0):
space = ' ' * shift
for comment in comments:
print(f"{space}- {comment['text']} : {comment['id']}")
def main():
root_project = Wrike.get_project_tree(with_fields=['tasks', 'comments'])
Wrike.print_project_tree(root_project, with_fields=['tasks', 'comments'])
with open('wrike.json', 'w') as f:
json.dump(root_project, f)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment