Created
November 14, 2018 02:46
-
-
Save yuhki50/15a9212b28ecd77f24b44e09253c35b6 to your computer and use it in GitHub Desktop.
export-wrike.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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