-
Notifications
You must be signed in to change notification settings - Fork 0
/
toggl.py
144 lines (126 loc) · 4.71 KB
/
toggl.py
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/python
#
# read rfid tags, translate to tasks, and send task updates to toggl.com
#
# input: <rfid tag number> <seconds>\n
from optparse import OptionParser
from sys import stdin
import base64
import urllib2
import yaml
import json
import datetime
USERAGENT = "toggl.py/punchclock"
class MethodRequest(urllib2.Request):
''' Used to create HEAD/PUT/DELETE/... requests with urllib2 '''
def __init__(self, url, data=None, headers={}, method="GET"):
urllib2.Request.__init__(self, url, data, headers)
self.set_method(method)
def set_method(self, method):
self.method = method.upper()
def get_method(self):
return getattr(self, 'method', urllib2.Request.get_method(self))
#TODO: remove the need for a yaml map of rfid->task
#TODO: turn the yaml map into a json map, so i dont need both formats.
# dictionary of tag number -> string
TAG_MAP = {}
TASKS = []
def updateTask(taskid, duration):
""" add duration to the duration of the task with the supplied id.
"""
TASKS = getTasks() # refresh our task list.
task = None
taskid = taskid
for t in TASKS:
if t['id'] == taskid:
task = t
break
task['duration'] += int(duration)
# now send up the new task.
posturl = "http://www.toggl.com/api/v3/tasks/%d.json" % task['id']
r = MethodRequest(posturl, data="{\"task\": %s }" % json.dumps(task), method="PUT")
r = addAuthHeader(r, options.apikey)
r.add_header("Content-type", "application/json")
print r.get_data()
print r.get_full_url()
f = urllib2.urlopen(r)
print f.read()
def createTask(taskobj):
""" creates a new task in Toggl with the specified contents."""
# now send up the new task.
#posturl = "http://www.toggl.com/api/v3/tasks.json"
posturl = "https://www.toggl.com/api/v6/time_entries.json"
r = MethodRequest(posturl, data=json.dumps(taskobj), method="POST")
r = addAuthHeader(r, options.apikey)
r.add_header("Content-type", "application/json")
print r.get_data()
print r.get_full_url()
f = urllib2.urlopen(r)
print f.read()
def addAuthHeader(request, apikey):
""" This is needed because the toggl servers dont do standard http basic auth.
"""
base64string = base64.encodestring('%s:%s' % (apikey, 'api_token')).replace('\n', '')
request.add_header("Authorization", "Basic %s" % base64string)
return request
def getTasks():
r = urllib2.Request("http://www.toggl.com/api/v3/tasks.json")
r = addAuthHeader(r, options.apikey)
f = urllib2.urlopen(r)
TASKS = (json.load(f))['data']
return TASKS
def getTaskJsonObject(cpn, duration):
"""Creates a Toggl task api object, using a JsonObject."""
starttime = datetime.datetime.utcnow() - datetime.timedelta(seconds=duration)
endtime = datetime.datetime.utcnow()
baseobj = {
'duration': duration,
'billable': True,
'start': starttime.isoformat(),
'stop': endtime.isoformat(),
'project' : {"id": 526871},
'created_with': USERAGENT,
'ignore_start_and_stop': True,
'description': '',
}
return {'time_entry': baseobj}
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-k", "--toggl_key", dest='apikey', help="Toggl api key")
parser.add_option("-t", "--tagmap", dest='mapfile',
help="yaml file containing tag id -> task mapping")
parser.add_option("-i", "--input", dest='input', default=None,
help="read input from the specified file/device")
parser.add_option("-m", "--min_time", dest='min_time', default=10,
help="events shorter than this will not be reported")
(options, args) = parser.parse_args()
if not options.apikey:
parser.error("--toggl_key is a required argument")
#if not options.mapfile:
# parser.error("--tagmap is a required argument")
#if options.mapfile:
# TAG_MAP = yaml.load(file(options.mapfile))
if options.input:
# input specified, read it.
inputfh = open(options.input)
else:
inputfh = stdin
while True:
s = inputfh.readline()
s = s.strip()
if not s or s[0] == '#':
continue
print "(%s)" % s
(duration, key) = s.split(" ", 1)
#print "key: %s" % key
if(TAG_MAP.has_key(key)):
print TAG_MAP[key]
if(int(duration) < options.min_time):
print "%s : event too short" % key
continue
createTask(getTaskJsonObject(TAG_MAP[key], int(duration)))
else:
print "SDLKFSDLFKJSDF"
print duration
createTask(getTaskJsonObject(key, int(duration)))
#print "unknown tag: %s" % key