229 lines
6.5 KiB
Python
229 lines
6.5 KiB
Python
from datetime import timezone
|
|
import dateutil.parser
|
|
from html.parser import HTMLParser
|
|
import sys
|
|
|
|
class AsanaObject(object):
|
|
def __init__(self, object_dict):
|
|
self.object_dict = object_dict
|
|
|
|
def id(self):
|
|
return self.object_dict['id']
|
|
|
|
def name(self):
|
|
if 'name' in self.object_dict:
|
|
return self.object_dict['name']
|
|
else:
|
|
return ''
|
|
|
|
class User(AsanaObject):
|
|
def workspaces(self):
|
|
return [AsanaObject(w) for w in self.object_dict['workspaces']]
|
|
|
|
class Task(AsanaObject):
|
|
def name(self):
|
|
if self.object_dict['completed']:
|
|
return '✓ %s' % super(Task, self).name()
|
|
return super(Task, self).name()
|
|
|
|
def assignee(self):
|
|
if 'assignee' in self.object_dict and self.object_dict['assignee']:
|
|
return User(self.object_dict['assignee'])
|
|
else:
|
|
return None
|
|
|
|
def atm_section(self):
|
|
return self.object_dict['assignee_status']
|
|
|
|
def description(self):
|
|
if 'html_notes' in self.object_dict:
|
|
parser = HTMLTextParser()
|
|
parser.feed(self.object_dict['html_notes'])
|
|
parser.close()
|
|
text = parser.get_formatted_text()
|
|
if (len(text) > 0):
|
|
return text
|
|
else:
|
|
return ""
|
|
elif 'notes' in self.object_dict:
|
|
return self.object_dict['notes']
|
|
else:
|
|
return ""
|
|
|
|
def due_date(self):
|
|
if 'due_at' in self.object_dict and self.object_dict['due_at']:
|
|
datetime = dateutil.parser.parse(self.object_dict['due_at'])
|
|
datetime = datetime.replace(tzinfo=timezone.utc).astimezone(tz=None)
|
|
return datetime.strftime('%b %d, %Y %H:%M')
|
|
elif 'due_on' in self.object_dict and self.object_dict['due_on']:
|
|
date = dateutil.parser.parse(self.object_dict['due_on'])
|
|
return date.strftime('%b %d, %Y')
|
|
else:
|
|
return 'no due date'
|
|
|
|
def parent(self):
|
|
if 'parent' in self.object_dict and self.object_dict['parent']:
|
|
return Task(self.object_dict['parent'])
|
|
else:
|
|
return None
|
|
|
|
def projects(self):
|
|
if 'projects' in self.object_dict:
|
|
return [Project(p) for p in self.object_dict['projects']]
|
|
else:
|
|
return []
|
|
|
|
def subtasks(self):
|
|
if 'subtasks' in self.object_dict:
|
|
return [Task(t) for t in self.object_dict['subtasks']]
|
|
else:
|
|
return []
|
|
|
|
def custom_fields(self):
|
|
if 'custom_fields' in self.object_dict:
|
|
return [CustomField(c) for c in self.object_dict['custom_fields']]
|
|
else:
|
|
return []
|
|
class Project(AsanaObject):
|
|
def description(self):
|
|
if 'notes' in self.object_dict:
|
|
return self.object_dict['notes']
|
|
else:
|
|
return ''
|
|
|
|
class CustomField(AsanaObject):
|
|
def string_value(self):
|
|
if 'text_value' in self.object_dict:
|
|
return str(self.object_dict['text_value'])
|
|
elif 'number_value' in self.object_dict:
|
|
return str(self.object_dict['number_value'])
|
|
elif 'enum_value' in self.object_dict and self.object_dict['enum_value']:
|
|
enum_value = AsanaObject(self.object_dict['enum_value'])
|
|
return str(enum_value.name())
|
|
|
|
return ''
|
|
|
|
class Strong(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return ('strong', self.body.text_format())
|
|
|
|
class Italic(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return ('italic', self.body.text_format())
|
|
|
|
class Underline(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return ('underline', self.body.text_format())
|
|
|
|
class Link(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return ('link', self.body.text_format())
|
|
|
|
class Tag(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return self.body.text_format()
|
|
|
|
class List(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return self.body.text_format()
|
|
|
|
class ListItem(object):
|
|
def __init__(self, body, indent):
|
|
self.body = body
|
|
self.indent = indent
|
|
|
|
def text_format(self):
|
|
return ('', [(' ' * self.indent), '• ', self.body.text_format(), '\n'])
|
|
|
|
class Text(object):
|
|
def __init__(self, body):
|
|
self.body = body
|
|
|
|
def text_format(self):
|
|
return self.body
|
|
|
|
class HTMLTextParser(HTMLParser):
|
|
def __init__(self):
|
|
self.text = []
|
|
self.tag_stack = []
|
|
self.indent = 0
|
|
super().__init__()
|
|
|
|
def handle_starttag(self, tag, attrs):
|
|
if tag == 'strong':
|
|
self.tag_stack.append(Strong)
|
|
elif tag == 'em':
|
|
self.tag_stack.append(Italic)
|
|
elif tag == 'u':
|
|
self.tag_stack.append(Underline)
|
|
elif tag == 'a':
|
|
self.tag_stack.append(Link)
|
|
elif tag == 'ul' or tag == 'ol':
|
|
self.indent += 2
|
|
self.tag_stack.append(List)
|
|
elif tag == 'li':
|
|
self.tag_stack.append(ListItem)
|
|
else:
|
|
self.tag_stack.append(Tag)
|
|
|
|
def handle_data(self, data):
|
|
self.text.append(Text(data))
|
|
|
|
def handle_endtag(self, tag):
|
|
data = self.text.pop() if len(self.text) > 0 else Text("")
|
|
Class = self.tag_stack.pop()
|
|
|
|
if tag == 'ul' or tag =='ol':
|
|
self.indent -= 2
|
|
|
|
if tag == 'li':
|
|
self.text.append(Class(data, self.indent))
|
|
else:
|
|
self.text.append(Class(data))
|
|
|
|
def get_formatted_text(self):
|
|
formatted = [t.text_format() for t in self.text]
|
|
return formatted
|
|
|
|
|
|
class Story(AsanaObject):
|
|
def creator(self):
|
|
if 'created_by' in self.object_dict:
|
|
return self.object_dict['created_by']['name'] + ' '
|
|
else:
|
|
return ''
|
|
|
|
def created_at(self):
|
|
if 'created_at' in self.object_dict:
|
|
return dateutil.parser.parse(self.object_dict['created_at']) \
|
|
.replace(tzinfo=timezone.utc).astimezone(tz=None)
|
|
else:
|
|
return ''
|
|
|
|
def text(self):
|
|
if 'html_text' in self.object_dict:
|
|
parser = HTMLTextParser()
|
|
parser.feed(self.object_dict['html_text'])
|
|
parser.close()
|
|
return parser.get_formatted_text()
|
|
else:
|
|
return [self.object_dict['text']]
|