Another version of Toggl-parser.
#!/usr/local/bin/python3 | |
import sys | |
import csv | |
import xlwt | |
import requests | |
import json | |
import pandas | |
from datetime import datetime | |
def parse_file(filename): | |
csv_file = sys.argv[1] | |
# if argument given raises an exception - we should try use a default name or file in the same dir w/ .csv? | |
wb = open(csv_file) | |
reader = csv.reader(wb) | |
data = [] | |
# We need Cols: 3, empty, 5, 7, 9 for `Project`, `Effort`, `Task | |
# description`, `Start date`, `End date` | |
first_row = True | |
for row in reader: | |
if first_row: # skip first row | |
first_row = False | |
continue | |
project = str(row[3]) | |
time = row[11] # We using `Duration` value for the effort calculation | |
effort = int(time[0:2]) + int(int(time[3:5])) / 60 + \ | |
int(int(time[6:7])) / 3600 # Hourly effort formula | |
task = str(row[5]) | |
started = str(row[7]) | |
completed = str(row[9]) | |
data.append((project, effort, task, started, completed)) | |
return data | |
def get_workspace(token): | |
print('Proceeding with your token, getting your workspace id now...') | |
r = requests.get('https://www.toggl.com/api/v8/workspaces', auth=(token, 'api_token')) | |
req = r.json() | |
r.status_code | |
r.raise_for_status() | |
workspace = req[0]['id'] # we know user's workspace id now | |
return workspace | |
def parse_online(token, workspace_id): | |
# TODO: add two more arguments for parsing requested period of time | |
print('Proceeding with your token, collecting your data now...') | |
since = '2018-10-01' # Begin of retrieved records | |
until = '2018-10-31' # End of retrieved period | |
r = requests.get("https://toggl.com/reports/api/v2/details?", auth=(token, 'api_token'), params={ | |
'workspace_id': workspace_id, | |
'page': '1', # we did 50 records. So this a minimum. Less will lead to fail? TODO: the rest | |
'since': since, | |
'until': until, | |
'user_agent': 'api_test' | |
}) | |
data = r.json() | |
''' | |
Or... The first request for amount of records retrieving (dry run). | |
Then we'll do a work request??? | |
''' | |
pages_amount = int(data['total_count'] / 50) | |
pages_remainder = int(data['total_count']) % 50 | |
print(pages_amount, pages_remainder) # this give us amount of loops (w/ 50 recs each) and a remainder | |
parsed = [] | |
for rec in range(00, 50): | |
project = data['data'] [rec] ['project'] | |
effort = ((lambda dur: dur / 1000 / 3600) (data['data'] [rec] ['dur'])) # Millisec -> Sec -> Hours in decimal (effort) | |
task = data['data'] [rec] ['description'] | |
started = data['data'] [rec] ['start'] | |
completed = data['data'] [rec] ['end'] | |
parsed.append((project, effort, task, started, completed)) | |
print(parsed) | |
return parsed | |
def export_xls(data): | |
xls_file = 'timereport.xls' # TODO: add date period to the filename automatically | |
book = xlwt.Workbook(encoding="utf-8") | |
date_format = xlwt.XFStyle() | |
date_format.num_format_str = 'yyyy/mm/dd' | |
sheet1 = book.add_sheet("Efforts") | |
# create DataFrame to remove duplicates | |
df = pandas.DataFrame( | |
data, columns=['project', 'effort', 'task', 'started', 'completed']) | |
# sum duplicates | |
df = df.groupby(['project', 'task', 'started', 'completed'] | |
).sum().reset_index() | |
# add header row to xls file | |
sheet1.write(0, 0, 'Project-Task') | |
sheet1.write(0, 1, 'Effort') | |
sheet1.write(0, 2, 'Description') | |
sheet1.write(0, 3, 'Started Date') | |
sheet1.write(0, 4, 'Completion Date') | |
for i, row in df.iterrows(): | |
sheet1.write(i+1, 0, row['project']) | |
sheet1.write(i+1, 1, row['effort']) | |
sheet1.write(i+1, 2, row['task']) | |
sheet1.write(i+1, 3, datetime.strptime( | |
row['started'], '%Y-%m-%d'), date_format) | |
sheet1.write(i+1, 4, datetime.strptime( | |
row['completed'], '%Y-%m-%d'), date_format) | |
i += 1 | |
book.save(xls_file) | |
print('The Toggl data has been successfully exported:',xls_file) | |
def print_usage(): | |
print('''Usage: python3 toggl.py <CSV filename> | <toggl API token> | |
python3 toggl.py <CSV file> - parse the given file and generate timereport.xls at the same directory | |
python3 toggl.py <toggle API token> - request detailed report from Toggl and generate timereport.xls | |
Supposed, that you have Toggl account already for start using this utility. | |
As for our company - the best practice will be the following: | |
- Create Client names i.e. `Microsoft` | |
- Create a bunch of Project names | |
formatted as `ProjectName.TypeOfActivity` i.e. `AppCenter.Development` | |
- Start track your every activity by using a dropdown menu | |
and by selecting the right `ProjectName.TypeOfActivity` value | |
- You all set! | |
Finally, you can either download a CSV-file from the Report page | |
(go https://toggl.com/app/reports/detailed/<your workspace id will be here>/period/thisMonth) | |
or use API-token (go https://toggl.com/app/profile for get your one) for the further parsing.''') | |
sys.exit() | |
if len(sys.argv) < 2: | |
print_usage() | |
argument = str(sys.argv[1]) | |
if argument[-4:] == '.csv': # the given argument ends with ".csv" | |
print('Parsing the file given:', argument) | |
export_xls(parse_file(argument)) | |
else: | |
print('Proceed with token given. Request data online and parsing ') | |
export_xls(parse_online(argument, get_workspace(argument))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment