def __init__(self, periph, config): self.config = config self.toggl = Toggl() self.toggl.setAPIKey(self.config["toggl"]["settings"]["token"]) self._populateProjects() self._populateMappings(self.config["mappings"]) super().__init__(periph)
def toggl_delete_entries_for_ids(ids, token=None): toggl = Toggl() if token is None: token = os.getenv("TOGGL_API_TOKEN") toggl.setAPIKey(token) for id_ in ids: endpoint = Endpoints.TIME_ENTRIES + f"/{id_}" toggl_http_request(toggl, endpoint, "DELETE")
class Toggl2GSuiteTest(unittest.TestCase): def setUp(self): self.api_key = os.environ["TOGGL_API_KEY"] self.toggl = Toggl() self.toggl.setAPIKey(self.api_key) # see https://stackoverflow.com/questions/19153462/get-excel-style-column-names-from-column-number LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @staticmethod def excel_style(row, col): """ Convert given row and column number to an Excel-style cell name. """ result = [] while col: col, rem = divmod(col - 1, 26) result[:0] = Toggl2GSuiteTest.LETTERS[rem] return "".join(result) + str(row) def test_toggl2gsuite(self): # have to do this year by year data = { "workspace_id": os.environ["WORKSPACE_ID"], } y = self.toggl.getDetailedReport(data) credentials = ServiceAccountCredentials.from_json_keyfile_name( os.environ["KEYFILE"], ["https://spreadsheets.google.com/feeds"] ) client = gspread.authorize(credentials) sheet = client.open_by_url(os.environ["SHEET_URL"]) worksheet = sheet.get_worksheet(0) wrote_header = False columns_to_write = [ "user", "updated", "start", "end", "client", "project", "description", "is_billable", "billable", ] cell_row = 0 for row_idx, rec in enumerate(y["data"]): if wrote_header == False: for col_idx, header in enumerate(columns_to_write): worksheet.update_acell( Toggl2GSuiteTest.excel_style(row_idx + 1, col_idx + 1), header ) wrote_header = True for col_idx, header in enumerate(columns_to_write): worksheet.update_acell( Toggl2GSuiteTest.excel_style(row_idx + 2, col_idx + 1), rec[header] )
def main(): # Read config file config = read_config_file() api_key = config.get('general', 'api_key').strip() api = Toggl() api.setAPIKey(api_key) projects = download_projects(api) dump_projects_as_csv(projects, sys.stdout)
def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] if self.api_key is None: raise Exception("Unable to execute api tests without an api key") self.workspace_id = os.environ['WORKSPACE_ID'] if self.workspace_id is None: raise Exception( "Unable to execute api tests without a workspace key to query") self.toggl = Toggl() self.toggl.setAPIKey(self.api_key)
def main(self): API_TOKEN = certification.load_json() if not API_TOKEN: print('[WARN]:Please set the API token in config.json') toggl = Toggl() toggl.setAPIKey(API_TOKEN) args = argument.get_argument() if args.function.lower() == 'start': workspace_id = self.get_workspace_id(toggl) self.get_project(toggl, workspace_id) self.start(toggl) elif args.function.lower() == 'stop': self.stop(toggl)
def get_data(self): toggl = Toggl() toggl.setAPIKey(self.config['api']) data = { 'workspace_id': workspace_id, 'user_agent': user_agent, 'since': self.last_month_first, 'until': self.last_month_last } self.response = toggl.request( "https://toggl.com/reports/api/v2/details", parameters=data) self.save_raw_data()
def team_weekly_report(destination, since, until, api_key, workspace): logger.info( "Downloading the team weekly report from {} until {} into {}".format( since, until, destination)) toggl = Toggl() toggl.setAPIKey(api_key) data = { 'workspace_id': workspace, # see the next example for getting a workspace id 'since': since, 'until': until } try: result = toggl.getSummaryReport(data) except Exception as e: logger.error("Unable to download the team weekly data {}".format(e)) return # Calculate hours and minutes total_ms = result['total_grand'] if total_ms: hours, minutes = divmod(total_ms / 1000 / 60, 60) time_str = "Total team hours: {:.0f}h {:.0f}m".format(hours, minutes) else: time_str = "Total team hours: No hours recorded" # Find all project worked on items_worked_on = [ item["title"]["time_entry"] for project in result["data"] for item in project["items"] ] if len(items_worked_on) == 0: items_worked_on = ["No tasks worked on for this time period"] # Calculate the pretty data for the start of the week date = datetime.strptime(since, "%Y-%m-%d") formatted_week = date.strftime("%B %d") formatted_items = "- " + "\n- ".join(items_worked_on) formatted_team_report = team_report_template.format( formatted_week, formatted_items, time_str) logger.info("Created team report:") logger.info(formatted_team_report) logger.info("Adding to team log file %s", destination) with open(destination, "a") as report: report.write(formatted_team_report) logger.info("Done team report")
def toggl_get_entries_raw(date: datetime.date, token=None): toggl = Toggl() if token is None: token = os.getenv("TOGGL_API_TOKEN") toggl.setAPIKey(token) start_date = datetime.datetime.combine(date, datetime.time()).astimezone() params = {"start_date": start_date.isoformat()} params["end_date"] = (start_date + datetime.timedelta(days=1) + datetime.timedelta(minutes=-1)).isoformat() print(date) time.sleep(2) togglentries = toggl.request(Endpoints.TIME_ENTRIES, params) return togglentries
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): """Set up Toggl from a config entry.""" hass.data[DOMAIN]["toggl"] = Toggl() for component in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
class TogglPyTests(unittest.TestCase): def setUp(self): self.api_key = os.environ["TOGGL_API_KEY"] if self.api_key is None: raise Exception("Unable to execute api tests without an api key") self.workspace_id = os.environ["WORKSPACE_ID"] if self.workspace_id is None: raise Exception( "Unable to execute api tests without a workspace key to query" ) self.toggl = Toggl() self.toggl.setAPIKey(self.api_key) def test_connect(self): response = self.toggl.request("https://api.track.toggl.com/api/v8/clients")
class Toggl2GSuiteTest(unittest.TestCase): def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] self.toggl = Toggl() self.toggl.setAPIKey(self.api_key) # see https://stackoverflow.com/questions/19153462/get-excel-style-column-names-from-column-number LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' @staticmethod def excel_style(row, col): """ Convert given row and column number to an Excel-style cell name. """ result = [] while col: col, rem = divmod(col - 1, 26) result[:0] = Toggl2GSuiteTest.LETTERS[rem] return ''.join(result) + str(row) def test_toggl2gsuite(self): # have to do this year by year data = { 'workspace_id': os.environ['WORKSPACE_ID'], } y = self.toggl.getDetailedReport(data) credentials = ServiceAccountCredentials.from_json_keyfile_name( os.environ['KEYFILE'], ['https://spreadsheets.google.com/feeds']) client = gspread.authorize(credentials) sheet = client.open_by_url(os.environ['SHEET_URL']) worksheet = sheet.get_worksheet(0) wrote_header = False columns_to_write = ['user', 'updated', 'start', 'end', 'client', 'project', 'description', 'is_billable', 'billable'] cell_row = 0 for row_idx, rec in enumerate(y['data']): if wrote_header == False: for col_idx, header in enumerate(columns_to_write): worksheet.update_acell(Toggl2GSuiteTest.excel_style(row_idx + 1, col_idx + 1), header) wrote_header = True for col_idx, header in enumerate(columns_to_write): worksheet.update_acell(Toggl2GSuiteTest.excel_style(row_idx + 2, col_idx + 1), rec[header])
def toggl_get_tasks(token=None) -> List[TglTask]: toggl = Toggl() if token is None: token = os.getenv("TOGGL_API_TOKEN") toggl.setAPIKey(token) workspaces = [] for e in _retry(lambda: toggl.getWorkspaces()): workspaces.append((e["id"], e["name"])) projects = [] for wid, wname in workspaces: for e in _retry(lambda: toggl.request(Endpoints.WORKSPACES + f"/{wid}/projects")) or []: projects.append((e["id"], e["name"])) ptasks = [] for pid, pname in projects: for e in _retry(lambda: toggl.getProjectTasks(pid)) or [{ "id": 0, "name": "" }]: ptasks.append(TglTask(pid, pname, e["id"], e["name"])) return ptasks
def get_entries(start, end, from_workspace_id, from_user_id): toggl = Toggl() toggl.setAPIKey(os.getenv('TOGGL_APIKEY')) response = toggl.request( f'https://toggl.com/reports/api/v2/details?workspace_id={from_workspace_id}&since={start}&until={end}&user_agent={user_agent}&uid={from_user_id}&include_time_entry_ids=true&user_ids={from_user_id}' ) if response['total_count'] > response['per_page']: raise Exception('Paging not supported, results exceed the page') for k, v in response.items(): if k != 'data': print(k, v) entries = [] for time_entry in response['data']: print(time_entry) entries.append(time_entry) return entries
def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] if self.api_key is None: raise Exception("Unable to execute api tests without an api key") self.workspace_id = os.environ['WORKSPACE_ID'] if self.workspace_id is None: raise Exception("Unable to execute api tests without a workspace key to query") self.toggl = Toggl() self.toggl.setAPIKey(self.api_key)
class Toggls(): def __init__(self, key): self.toggl = Toggl() self.toggl.setAPIKey(key) def get_Workspaces(self): return self.toggl.getWorkspaces() def getprojectsinworkspace(self, id): urls = "https://www.toggl.com/api/v8/workspaces/" + str(id) + "/projects" return self.toggl.request(urls) def get_workspace(self, name): return self.toggl.getWorkspace(name) def make_time_entry(self, pid, workout): start = workout[1][6:10] + "-" + workout[1][:2] + "-" + workout[1][3:5] + "T" + workout[1][12:] + ".000Z" time = float(workout[2][0])*60*60 + float(workout[2][2:4])*60 + float(workout[2][5:7]) url = 'https://www.toggl.com/api/v8/time_entries' data = { "time_entry": { "description":"Workout", "tags":[""], "duration": time, "start": start, "pid": pid, "created_with":"api" } } return self.toggl.postRequest(url, parameters=data)
def _loadActiviy(self): toggl = Toggl() toggl.setAPIKey(self._token) self._report_date = self._daily_date - timedelta(1) self.friday_text = '' if self._report_date.isoweekday() is 6 or self._report_date.isoweekday() is 7: self._report_date = self._daily_date - timedelta(3 if self._daily_date.isoweekday() is 1 else 2) self.friday_text = " (Friday)" self.report_day = '{0:%Y-%m-%d}'.format(self._report_date) me_info = toggl.request(toggl_urls.me) self._username = me_info['data']['fullname'] summary_url = toggl_urls.summary + "?workspace_id={}&since={}&until={}&user_agent=api_test".format( self._workspace_id, self.report_day, self.report_day) response = toggl.request(summary_url) activity = {} default_project = conf_manager.get_default_project() for data in response['data']: project_name = default_project if None == data['title']['project'] else data['title']['project'] activity[project_name] = [] for item in data['items']: hours = self.millis_to_hours(item['time']) self._total_hours += hours activity[project_name].append(Task(item['title']['time_entry'], project_name, hours).serialize()) self._activity = activity return activity
def _get_toggl_client(api_key): client = Toggl() client.setAPIKey(api_key) try: client.getWorkspaces() except HTTPError: raise click.BadParameter('Invalid api key or connection problem') return client
def user_weekly_report(directory, since, until, api_key, users, workspace): """ Downloads each users weekly reports as a summary and details pdf into their own directories. :param workspace: :param api_key: The toggl api key to use. :param users: The dictionary are users with the key as the user id and the values as the full name. :param directory: The root destination directory. Each user will have a sub-directory created for their reports :param since: The start date in the form yyyy-MM-dd :param until: the end data in the form yyyy-MM-dd. Files will be prepended with this date string. :return: None """ logging.info( "Downloading user weekly reports from {} until {} into {}".format( since, until, directory)) toggl = Toggl() toggl.setAPIKey(api_key) for uid, name in users.items(): logger.info("Downloading reports for {}".format(name)) name = users[uid] data = { 'workspace_id': workspace, # see the next example for getting a workspace id 'since': since, 'until': until, 'user_ids': uid } folder = path.join(directory, name) if not path.exists(folder): logger.info("Creating the folder {}".format(folder)) makedirs(folder) details = path.join(folder, until + "-details.pdf") summary = path.join(folder, until + "-summary.pdf") try: toggl.getDetailedReportPDF(data, details) logger.info("Downloaded {}".format(details)) toggl.getSummaryReportPDF(data, summary) logger.info("Downloaded {}".format(summary)) except Exception as e: logging.error(e)
def toggl_add_entries(entries: List[TglStandardEntry], tasks: List[TglTask], token=None): toggl = Toggl() if token is None: token = os.getenv("TOGGL_API_TOKEN") toggl.setAPIKey(token) taskmap = {} for t in tasks: k = t.project_name, t.task_name v = t.project_id, t.task_id taskmap[k] = v togglentries = [] for i, entry in enumerate(entries, start=1): try: try: pid, tid = taskmap[(entry.project, entry.task)] except KeyError: raise ConvertingError( f"{entry.project}, {entry.task} not found") togglentry = { "description": entry.description, "pid": pid, "tid": tid if tid else None, "start": entry.start.astimezone().isoformat(), "duration": entry.duration.seconds, "created_with": "easytrack", } togglentries.append(togglentry) except ConvertingError as e: e.i = i e.line = e raise for i, togglentry in enumerate(togglentries, start=1): try: try: print(i, '/', len(togglentries)) time.sleep(2) resp = toggl.postRequest(Endpoints.TIME_ENTRIES, {"time_entry": togglentry}) except urllib.error.HTTPError as e: raise TogglError(body=e.fp.read().decode(), underlying=e) resp = toggl.decodeJSON(resp) if resp.get("data") is None: raise ConvertingError(f"data not found in resp {resp}") except ConvertingError as e: e.i = i e.line = e raise
def get_projects(): """Since the current project function in PyToggl doesn't work, I made my own hacky version. Gets all projects assigned to a client and returns it as a list""" toggl = Toggl() toggl.setAPIKey(TOGGL_TOKEN) clients = toggl.getClients() toggl_projects = [] for client in clients: projects = toggl.getClientProjects(client["id"]) if projects != None: for project in projects: toggl_projects.append(project) return toggl_projects
def save_entries(entries, workspace_id, user_id, project_id, hourdiff_to_utc): toggl = Toggl() toggl.setAPIKey(os.getenv('TOGGL_APIKEY')) for entry in entries: start = entry['start'] start_date = datetime.datetime.strptime(start, '%Y-%m-%dT%H:%M:%S%z') y = start_date.year m = start_date.month d = start_date.day h = start_date.hour desc = entry['description'] print(entry['dur']) toggl.createTimeEntry(round(entry['dur'] / 3600000.0, 1), description=desc, projectid=project_id, year=y, month=m, day=d, hour=h, hourdiff=hourdiff_to_utc)
def __init__(self): self.config = load_config() api_token = self.config['toggl']['token'] self.toggl = Toggl() self.toggl.setAPIKey(api_token)
class TogglApi: def __init__(self): self.config = load_config() api_token = self.config['toggl']['token'] self.toggl = Toggl() self.toggl.setAPIKey(api_token) def preset_projects(self): return self.config['toggl']['preset_projects'] def current_timer(self): timer = self.toggl.currentRunningTimeEntry()['data'] if timer: if 'pid' in timer: project = self.get_project_name(timer['pid']) else: project = ['Kein Projekt', (244, 244, 6)] timer_dic = { 'name': timer.get('description', ""), 'id': timer['id'], 'start_time': datetime.fromtimestamp(int(timer['duration']) * -1), 'project_name': project[0], 'project_color': project[1] } # start = datetime.strptime(timer['start'],"%Y-%m-%dT%H:%M:%S+00:00") return timer_dic else: return { 'name': "", 'id': "1234", 'start_time': datetime.fromtimestamp(1542385078), 'project_name': "Kein Projekt", 'project_color': (30, 0, 0) } def get_project_name(self, pid): project = self.toggl.getProject(pid)['data'] name = project['name'] try: color = self.hex_to_rgb(project['hex_color']) color = (int(color[0] / 2), int(color[1] / 2), int(color[2] / 2)) except (): color = (200, 200, 200) return name, color def start_timer(self, project_name, description): print(self.config['toggl']['project_ids'][project_name]) self.toggl.startTimeEntry( description, self.config['toggl']['project_ids'][project_name]) def stop_timer(self): current_timer_id = self.current_timer()['id'] if current_timer_id: self.toggl.stopTimeEntry(current_timer_id) return True return False @staticmethod def hex_to_rgb(hex_str): hex = hex_str[1:] # remove pound sign # https://stackoverflow.com/questions/29643352/converting-hex-to-rgb-value-in-python return tuple(int(hex[i:i + 2], 16) for i in (0, 2, 4))
def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] self.toggl = Toggl() self.toggl.setAPIKey(self.api_key)
import sys # Integration imports from credentials import TOGGL_TOKEN, AIRTABLE_API_KEY from toggl.TogglPy import Toggl from airtable import Airtable from airtable_integrations import * import gcal #Utilities import re from pprint import pprint from task_dicts import event_exclude import urllib toggl = Toggl() toggl.setAPIKey(TOGGL_TOKEN) offset = int(sys.argv[1]) #Generate today-string index = dt.today() + datetime.timedelta(offset) index_midnight = index.replace(hour=0, minute=1) index_formatted = index_midnight.isoformat() + 'Z' index_str = dt.strftime(index, '%Y-%m-%d') day_after_index = index + datetime.timedelta(1) day_after_index_midnight = day_after_index.replace(hour=0, minute=1) day_after_index_formatted = day_after_index_midnight.isoformat() + 'Z'
def __init__(self, api_key): # create a Toggl object and set our API key self.toggl = Toggl() self.toggl.setAPIKey(api_key)
class TogglTimesheets: def __init__(self, api_key): # create a Toggl object and set our API key self.toggl = Toggl() self.toggl.setAPIKey(api_key) def _get_raw_timelogs(self, start_date=None, end_date=None): # Add filters params = {} if start_date: params["start_date"] = start_date if end_date: params["end_date"] = end_date # Make request and return return self.toggl.request(Endpoints.TIME_ENTRIES, parameters=params) def _get_raw_timelogs_last_n_days(self, n_days): last_n_days = datetime.utcnow() - timedelta(days=n_days) last_n_days_str = last_n_days.replace(microsecond=0, tzinfo=timezone.utc).isoformat() return self._get_raw_timelogs(start_date=last_n_days_str) @staticmethod def _parse_timelog(raw): """ { 'start': '2019-05-11T12:19:39+00:00', 'stop': '2019-05-11T12:40:27+00:00', 'description': 'Trying to deploy mongodb', 'tags': ['BB-1212'], 'duronly': False, } """ if raw.get('duronly', False): raise ("Error, timelog with duronly = true") tags = raw.get('tags', []) ticket = None dd = False ff = False for tag in tags: if ISSUE_REGEX.match(tag): ticket = tag elif tag == 'DD': dd = True elif tag == 'FF': ff = True if not ticket and 'description' in raw: possible = ISSUE_REGEX.findall(raw['description']) if possible: # TODO Dividing to multiple tickets ticket = possible[0] raw['description'] = raw['description'].strip(ticket).strip() if 'description' not in raw: # Shouldn't exist, but alas raw['description'] = 'NO DESCRIPTION' start = datetime.strptime(raw['start'], DATETIME_FORMAT) end = datetime.strptime(raw['stop'], DATETIME_FORMAT) return Timelog(ticket=ticket, date=start, time=end - start, description=raw['description'], ff_time=ff, dd_time=dd) def get_timelogs_last_n_days(self, n_days=1): raw_logs = self._get_raw_timelogs_last_n_days(n_days) result = { 'complete': list(), 'incomplete': list(), } for item in raw_logs: if 'stop' not in item: # Ignore currently running continue timelog = self._parse_timelog(item) if timelog.ticket: result['complete'].append(timelog) else: result['incomplete'].append(timelog) return result def get_timelogs(self, start_date, end_date): start_date_str = start_date.replace(microsecond=0, tzinfo=timezone.utc).isoformat() end_date_str = end_date.replace(microsecond=0, tzinfo=timezone.utc).isoformat() raw_logs = self._get_raw_timelogs(start_date=start_date_str, end_date=end_date_str) result = { 'complete': list(), 'incomplete': list(), } for item in raw_logs: if 'stop' not in item: # Ignore currently running continue timelog = self._parse_timelog(item) if timelog.ticket: result['complete'].append(timelog) else: result['incomplete'].append(timelog) return result
class TogglPyTests(unittest.TestCase): def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] if self.api_key is None: raise Exception("Unable to execute api tests without an api key") self.workspace_id = os.environ['WORKSPACE_ID'] if self.workspace_id is None: raise Exception("Unable to execute api tests without a workspace key to query") self.toggl = Toggl() self.toggl.setAPIKey(self.api_key) def test_connect(self): response = self.toggl.request("https://www.toggl.com/api/v8/clients") self.assertTrue(response is not None) def test_putTimeEntry(self): request_args = { 'workspace_id': self.workspace_id, } entries = self.toggl.getDetailedReport(request_args) #for this tests I'm tagging my Pomodoro Entries missing_projects = [r for r in entries['data'] if r['project'] is None and 'Pomodoro' in r['description'] ] me = missing_projects[0] me_id = me['id'] #remember for later #I've tagged my pomodoro entries as Self/Self cp = self.toggl.getClientProject("Self", "Self") project_id = cp['data']['id'] me['pid'] = project_id #his is the new stuff response = self.toggl.putTimeEntry({"id": me_id, "pid":project_id}) self.assertTrue(response is not None) self.assertTrue('data' in response) self.assertTrue(response['data']['pid'] == project_id) def test_getDetailedReportCSV(self): data = { 'workspace_id': self.workspace_id, } csvfile = 'data.csv' self.toggl.getDetailedReportCSV(data, csvfile) self.assertTrue(os.path.isfile(csvfile)) os.remove(csvfile) data = self.toggl.getDetailedReportCSV(data) self.assertTrue(data is not None) def test_getDetailedReport(self): data = { 'workspace_id': self.workspace_id, } d = self.toggl.getDetailedReport(data) self.assertTrue(d is not None) self.assertTrue(len(d.keys()) > 0 ) fields = ['total_count', 'total_currencies', 'total_billable', 'data'] for f in fields: self.assertTrue(f in d.keys()) data = d['data'] self.assertTrue(len(data)>0) dr = data[0] self.assertTrue('client' in dr) self.assertTrue('start' in dr) self.assertTrue('end' in dr) self.assertTrue('task' in dr) self.assertTrue('user' in dr) self.assertTrue('project' in dr)
def _get_toggl(user: User) -> Toggl: toggl = Toggl() toggl.setAPIKey(user.togglcredentials.api_key) return toggl
#get total amount of productivity in last 7 days from toggl.TogglPy import Toggl toggl = Toggl() toggl.setAPIKey('53a2d3c3856e1ef39982074936cd0c51') response = toggl.request("https://toggl.com/reports/api/v2/weekly") print(response)
class TogglPyTests(unittest.TestCase): def setUp(self): self.api_key = os.environ['TOGGL_API_KEY'] if self.api_key is None: raise Exception("Unable to execute api tests without an api key") self.workspace_id = os.environ['WORKSPACE_ID'] if self.workspace_id is None: raise Exception( "Unable to execute api tests without a workspace key to query") self.toggl = Toggl() self.toggl.setAPIKey(self.api_key) def test_connect(self): response = self.toggl.request( "https://api.track.toggl.com/api/v8/clients") self.assertTrue(response is not None) def test_putTimeEntry(self): request_args = { 'workspace_id': self.workspace_id, } entries = self.toggl.getDetailedReport(request_args) #for this tests I'm tagging my Pomodoro Entries missing_projects = [ r for r in entries['data'] if r['project'] is None and 'Pomodoro' in r['description'] ] me = missing_projects[0] me_id = me['id'] #remember for later #I've tagged my pomodoro entries as Self/Self cp = self.toggl.getClientProject("Self", "Self") project_id = cp['data']['id'] me['pid'] = project_id #his is the new stuff response = self.toggl.putTimeEntry({"id": me_id, "pid": project_id}) self.assertTrue(response is not None) self.assertTrue('data' in response) self.assertTrue(response['data']['pid'] == project_id) def test_getDetailedReportCSV(self): data = { 'workspace_id': self.workspace_id, } csvfile = 'data.csv' self.toggl.getDetailedReportCSV(data, csvfile) self.assertTrue(os.path.isfile(csvfile)) os.remove(csvfile) data = self.toggl.getDetailedReportCSV(data) self.assertTrue(data is not None) def test_getDetailedReport(self): data = { 'workspace_id': self.workspace_id, } d = self.toggl.getDetailedReport(data) self.assertTrue(d is not None) self.assertTrue(len(d.keys()) > 0) fields = ['total_count', 'total_currencies', 'total_billable', 'data'] for f in fields: self.assertTrue(f in d.keys()) data = d['data'] self.assertTrue(len(data) > 0) dr = data[0] self.assertTrue('client' in dr) self.assertTrue('start' in dr) self.assertTrue('end' in dr) self.assertTrue('task' in dr) self.assertTrue('user' in dr) self.assertTrue('project' in dr)
#!/usr/bin/env python # # LaunchBar Action Script # from toggl.TogglPy import Toggl from requests import HTTPError import datetime # %% toggl = Toggl() # fill your own E-Mail and Password. toggl.setAuthCredentials('<EMAIL>', '<PASSWORD>') # %% try: currentTimer = toggl.currentRunningTimeEntry() if currentTimer['data'] is None: print('No Time Entry Runnig Now.') else: stoppedEntry = toggl.stopTimeEntry(currentTimer['data']['id'])['data'] duration_str = str(datetime.timedelta(0, stoppedEntry['duration'])) print('Stopped: {}, Have Run {}.'.format(stoppedEntry['description'], duration_str)) except HTTPError as e: print(e)
class TogglTimesheets: def __init__(self, api_key): # create a Toggl object and set our API key self.toggl = Toggl() self.toggl.setAPIKey(api_key) def _get_raw_timelogs(self, start_date=None, end_date=None): # Add filters params = {} if start_date: params["start_date"] = start_date if end_date: params["start_date"] = end_date # Make request and return return self.toggl.request(Endpoints.TIME_ENTRIES, parameters=params) def _get_raw_timelogs_last_n_days(self, n_days): last_n_days = datetime.utcnow() - timedelta(days=n_days) last_n_days_str = last_n_days.replace(microsecond=0, tzinfo=timezone.utc).isoformat() return self._get_raw_timelogs(start_date=last_n_days_str) @staticmethod def _parse_timelog(raw): """ { 'start': '2019-05-11T12:19:39+00:00', 'stop': '2019-05-11T12:40:27+00:00', 'description': 'Trying to deploy mongodb', 'tags': ['BB-1212'], 'duronly': False, } """ if raw.get('duronly', False): print(raw) raise ("Error, timelog with duronly = true") tags = raw['tags'] ticket = None dd = False ff = False for tag in tags: if re.match(ISSUE_REGEX, tag): ticket = tag elif tag == 'DD': dd = True elif tag == 'FF': ff = True start = datetime.strptime(raw['start'], DATETIME_FORMAT) end = datetime.strptime(raw['stop'], DATETIME_FORMAT) return TIMELOG(ticket=ticket, date=start, time=end - start, description=raw['description'], ff_time=ff, dd_time=dd) def get_timelogs_last_n_days(self, n_days=1): raw_logs = self._get_raw_timelogs_last_n_days(n_days) result = { 'complete': list(), 'incomplete': list(), } for item in raw_logs: timelog = self._parse_timelog(item) if timelog.ticket: result['complete'].append(timelog) else: result['incomplete'].append(timelog) return result