forked from miracle2k/linuxutils
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetflow-export.py
More file actions
Latest commit
117 lines (93 loc) · 3.69 KB
/
Copy pathgetflow-export.py
File metadata and controls
117 lines (93 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""Process a data export from Flow (getflow.com).
Flow data is a zip that extract looks like this:
index.html
lists/
{List}.html
{Group}/
List.html
Expects to be given the path to the root directory.
"""
importsys
importos
importdatetime
fromtimeimportmktime
fromos.pathimportjoin, exists
importjson
frombs4importBeautifulSoup
fromdateutilimportparserasdateparser
defdetail(task_el, name, transform=None, optional=False):
"""Get the detail "name" from the task element."""
foritemintask_el.find(class_='task-info').findAll('li'):
#print filter(bool, ([
# (s if isinstance(s, basestring) else s.text).strip(' :\n\r\t')
# for s in item.children]))
title, value=filter(bool, ([
(sifisinstance(s, basestring) elses.text).strip(' :\n\r\t')
forsinitem.children]))
iftitle.strip().lower() ==name.lower():
iftransformandvalue:
value=transform(value)
returnvalue
ifoptional:
returnNone
raiseValueError('detail %s not found for %s'% (name, task_el))
deftext(el):
"""Text of an element, or None."""
ifnotel:
returnNone
returnel.text.strip()
defprocess_folder(filename):
print>>sys.stderr, 'Processing %s'%filename
withopen(filename, 'r') asf:
soup=BeautifulSoup(f.read())
list_name=soup.title(text=True)[0]
task_elems=soup.find_all("li", class_="task")
print>>sys.stderr, 'Found list {0} with {1} tasks'.format(list_name, len(task_elems))
tasks= []
forelintask_elems:
task= {
'title': list(el.find('a', class_='body').children)[0].strip(),
'completed': 'completed'inel['class'],
'created-by': detail(el, 'Created by'),
'assigned-to': detail(el, 'Assigned to'),
'created-on': detail(el, 'Created on', dateparser.parse),
'completed-on': detail(el, 'Completed on', dateparser.parse, True),
'followers': detail(el, 'Followers'),
'activities': []
}
tasks.append(task)
#completed_at = ac.find(class_='completed-at'.text.strip())
#if completed_at:
# task['completed_at'] = dateparser.parse(completed_at)
foractivity_elinel.findAll('li', class_='activity'):
task['activities'].append({
'summary': activity_el.find(class_='summary').text.strip(),
'detail': text(activity_el.find(class_='activity-detail')),
'date': activity_el.find(class_='date').text.strip()
})
return (list_name, tasks)
defmain(prog, argv):
iflen(argv) !=1:
print>>sys.stderr, 'Usage: {0} EXTRACTED_EXPORT_ZIP_DIR'.format(prog)
return
p=argv[0]
ifnotexists(join(p, 'lists')):
print>>sys.stderr, "No lists/ folder, I need the path where index.html is located."
lists= {}
fordirpath, dirnames, filenamesinos.walk(join(p, 'lists/')):
forfilenameinfilter(lambdaf: f.endswith('.html'), filenames):
list, tasks=process_folder(join(dirpath, filename))
list_name=list
i=0
whilelist_nameinlists:
list_name='%s (%s)'.format(list, i)
i+=1
lists[list_name] =tasks
classDateEncoder(json.JSONEncoder):
defdefault(self, obj):
ifisinstance(obj, datetime.datetime):
returnint(mktime(obj.timetuple()))
returnjson.JSONEncoder.default(self, obj)
printjson.dumps(lists, cls=DateEncoder, indent=4)
if__name__=='__main__':
main(sys.argv[0], sys.argv[1:])