def parse_request(data_form): ''' Parses the request using the specified data_form. Args: data_form: The data form from the request Returns: A response object based off of how the request was parsed. ''' # TODO: add try/except here # if exists, in the form of (proj_id, proj_name) proj_info = _filter_project(data_form) if proj_info is not None: proj_id, proj_name = proj_info # create repo info in database if doesn't exist if not repo.repo_exists(proj_id, proj_name): repo.set_repo(proj_id, proj_name) # if exists in the form of (sender_id, sender_name) sender_info = _filter_sender(data_form) if sender_info is not None: sender_id, sender_name = sender_info # make sure git info for this user is set in DB repo.check_git_user(sender_id, sender_name) # check their state, to notify them that they might be offline slack_uuid = repo.get_slack_uuid(sender_id, sender_name) if slack_uuid is not None: user_state = user_session.get_state(slack_uuid) if user_state == 'OFFLINE': # send slack message to channel settings.getSlack().send_message(contents='I see you sent a commit for the ' + str(proj_name) + ' repository. You know you are OFFLINE with Epoch right?', channel=str(slack_uuid), username='******', icon_emoji=':loudspeaker:') if 'commits' in data_form: commit_data = data_form['commits'] # for each commit for c in commit_data: message_data = str(c['message'].encode('ascii', 'ignore')) commit_url = str(c['url']) repo.create_commit_log(repo_id=proj_id, user_id=slack_uuid, commit_text=message_data, commit_url=commit_url) return Response('Okay'), 200
def force_logout_users(): ''' Forces all the users to logout, sending them a notification. ''' users = user.get_all_users() if users is not None and len(users) > 0: for uuid, username in users: state = user_session.get_state(uuid) if state != 'OFFLINE': print('Force logging out ' + str(username) + ' as their state was ' + str(state)) LOG.debug( str(time.ctime(time.time())) + ': Force logging out ' + str(username) + ' as their state was ' + str(state)) # set the new state user_session.set_state(uuid, 'OFFLINE') user.log_state_change(uuid, 'OFFLINE', state) # get how long they worked msecs = user_session.get_work_time(uuid) start_time = user_session.get_session_timestamp(uuid) end_time = time.strftime('%Y-%m-%d %H:%M:%S') # create the session log user_session.create_user_session_log(uuid, msecs, start_time, end_time) # reset their work time to 0 user_session.set_work_time(uuid, 0) user_session.set_session_timestamp(uuid) # send slack message to channel slack_server.send_message( contents= 'Epoch was restarted and you were logged out. Please use `/epoch start`.', channel='@' + str(username), username='******', icon_emoji=':loudspeaker:')
def handle_list_command(): ''' Handles the parsing of the list command. This allows the user to see what users we are tracking. ''' # USER --- STATE --- LAST LOGIN --- HOURS WORKED --- GOAL HOURS all_users = user.get_all_users() if all_users is not None and len(all_users) > 0: for uuid, name in all_users: state = user_session.get_state(uuid) last_login = user_session.get_session_timestamp(uuid) total_hours = '%.2f' % user_session.get_total_worked(uuid) goal_hours = user.get_goal_total(uuid) data = (name, state, last_login, total_hours, goal_hours) print('[' + str(name) + '][' + str(state) + '] was last seen at ' + str(last_login) + '. They are at ' + str(total_hours) + ' / ' + str(goal_hours) + ' hours.')
def parse_request(data_form): ''' Parses the request using the specified data_form. Args: data_form: The data form from the request Returns: A response object based off of how the request was parsed. ''' # TODO: add try/except here # if exists, in the form of (repo_id, repo_name) repo_info = _filter_repository(data_form) if repo_info is not None: repo_id, repo_name = repo_info # create repo info in database if doesn't exist if not repo.repo_exists(repo_id, repo_name): repo.set_repo(repo_id, repo_name) valid = False # filter out for only UPDATEs else merging branches is hell if 'refChanges' in data_form: ref_changes = data_form['refChanges'] if ref_changes is not None and len(ref_changes) > 0: for rc in ref_changes: if 'type' in rc: change_type = str(rc['type']) if change_type == 'UPDATE': valid = True else: print('Unable to validate this payload, as the ref change type was ' + str(change_type)) if 'changesets' in data_form and valid: change_sets = data_form['changesets'] if 'values' in change_sets: values = change_sets['values'] if values is not None and len(values) > 0: for v in values: # extract the toCommit if 'toCommit' in v: to_commit = v['toCommit'] committer_data = _filter_committer(to_commit) # if committer exists if committer_data is not None: committer_name, committer_email = committer_data # check their state, to notify them that they might be offline slack_uuid = _get_slack_uuid(committer_email) if slack_uuid is not None: user_state = user_session.get_state(slack_uuid) if user_state == 'OFFLINE': # send slack message to channel settings.getSlack().send_message(contents='I see you sent a commit for the ' + str(repo_name) + ' repository. You know you are OFFLINE with Epoch right?', channel=str(slack_uuid), username='******', icon_emoji=':loudspeaker:') commit_id = to_commit['id'] message_data = str(to_commit['message'].encode('ascii', 'ignore')) # find the first commit url commit_url = _filter_url(v) # create the commit log repo.create_commit_log(repo_id=repo_id, user_id=slack_uuid, commit_text=message_data, commit_url=commit_url) else: print('Unable to validate this payload, as the form was not valid.') return Response('Okay'), 200
def handle_command(user_obj, command, data): ''' Handles the command given by the request. Args: user_obj: The object that represents the user command: The command from the request data: The data form that is the request Returns: A response object based off of how the request's command was handled. ''' # get the current state of the user state = user_session.get_state(user_obj.uuid) if command == 'START': if state == 'OFFLINE': # set the new state user_session.set_state(user_obj.uuid, 'ONLINE') user.log_state_change(user_obj.uuid, 'ONLINE', 'OFFLINE') # the timestamp needs updated user_session.set_work_time(user_obj.uuid, 0) user_session.set_session_timestamp(user_obj.uuid) # send slack message to channel slack_server.send_message(contents=str(user_obj.username) + ' is now online!', channel='#work-progress', username='******', icon_emoji=':green_heart:') return Response(response=json.dumps( build_login_response(user_obj)), status=200, mimetype='application/json') else: return Response( 'In order to use [start], you must be in OFFLINE mode. You are in ' + str(state) + ' mode!'), 200 elif command == 'STOP': if state == 'ONLINE': # set the new state user_session.set_state(user_obj.uuid, 'OFFLINE') user.log_state_change(user_obj.uuid, 'OFFLINE', 'ONLINE') # get how long they worked msecs = user_session.get_work_time(user_obj.uuid) start_time = user_session.get_session_timestamp(user_obj.uuid) end_time = time.strftime('%Y-%m-%d %H:%M:%S') # get the user's goal hours goal_hours = user.determine_goal_hours_today(user_obj.uuid) worked_hours = '%.2f' % (msecs / 3600000.0) # create the session log user_session.create_user_session_log(user_obj.uuid, msecs, start_time, end_time) # reset their work time to 0 user_session.set_work_time(user_obj.uuid, 0) user_session.set_session_timestamp(user_obj.uuid) # send slack message to channel slack_server.send_message(contents=str(user_obj.username) + ' is now offline...', channel='#work-progress', username='******', icon_emoji=':broken_heart:') # construct a payload that shows the commit logs handle_logout_payload(user_obj, start_time, end_time, worked_hours, goal_hours) return Response(response=json.dumps( build_logout_response(user_obj)), status=200, mimetype='application/json') else: return Response( 'In order to use [stop], you must be in ONLINE mode. You are in ' + str(state) + ' mode!'), 200 elif command == 'RESUME': if state == 'PAUSED': # set the new state user_session.set_state(user_obj.uuid, 'ONLINE') user.log_state_change(user_obj.uuid, 'ONLINE', 'PAUSED') # send slack message to channel slack_server.send_message(contents=str(user_obj.username) + ' is back from their break!', channel='#work-progress', username='******', icon_emoji=':green_heart:') return Response(response=json.dumps( build_resume_response(user_obj)), status=200, mimetype='application/json') else: return Response( 'In order to use [resume], you must be in PAUSED mode. You are in ' + str(state) + ' mode!'), 200 elif command == 'PAUSE': if state == 'ONLINE': # set the new state user_session.set_state(user_obj.uuid, 'PAUSED') user.log_state_change(user_obj.uuid, 'PAUSED', 'ONLINE') # send slack message to channel slack_server.send_message(contents=str(user_obj.username) + ' went for a break!', channel='#work-progress', username='******', icon_emoji=':yellow_heart:') return Response(response=json.dumps( build_pause_response(user_obj)), status=200, mimetype='application/json') else: return Response( 'In order to use [pause], you must be in ONLINE mode. You are in ' + str(state) + ' mode!'), 200 elif command == 'INFO': return Response(response=json.dumps(build_info_response(user_obj)), status=200, mimetype='application/json') elif command == 'STATUS': # temporarirly removes auth check # check if it's an authorized user if user_obj.username == 'stephen' or user_obj.username == 'peraldon' or 1 == 1: return Response(response=json.dumps( build_status_response(user_obj)), status=200, mimetype='application/json') else: return Response('You are not authorized for this command.'), 200 return Response( 'Unknown command! Try /epoch [start|stop|pause|resume|info]'), 200
def build_status_response(user_obj): ''' Builds the status response for the specified user. Args: user_obj: The object representation for the specified user Returns: The Python dictionary that can be converted to JSON and sent as a response. ''' # USER --- STATE --- LAST LOGIN --- HOURS WORKED --- GOAL HOURS all_users = user.get_all_users() if all_users is not None and len(all_users) > 0: # construct the response message with the attachment message = slack_api.Message() for uuid, name in all_users: state = user_session.get_state(uuid) last_login = user_session.get_session_timestamp(uuid) total_hours = '%.2f' % user_session.get_total_worked(uuid) goal_hours = user.get_goal_total(uuid) data = (name, state, last_login, total_hours, goal_hours) # create the attachment contents = {} contents['title'] = str(name) # TODO maybe a link to our workers page? contents['title_link'] = COMPANY_URL # color the attachment based off of state if state == 'ONLINE': contents['color'] = "good" elif state == 'OFFLINE': contents['color'] = "danger" elif state == 'PAUSED': contents['color'] = "warning" # Determine the text of the attachment #contents['text'] = 'Last state change at ' + str(last_login) + ' EST.' # build the hours fields = [] f1 = {} f1['title'] = 'Total Hours (month)' f1['value'] = total_hours f1['short'] = True f2 = {} f2['title'] = 'Goal Hours (month)' f2['value'] = goal_hours f2['short'] = True fields.append(f1) fields.append(f2) contents['fields'] = fields if type(contents) is dict: # general footer contents['footer'] = 'Epoch API' contents['footer_icon'] = ICON_URL if last_login is not None: # attach the timestamp contents['ts'] = int(last_login.strftime('%s')) # add the attachment message.add_attachment(contents) return message.get_contents() else: return Response( 'Unexpected error occurred locally when parsing STATE request.' ), 200
def build_info_response(user_obj): ''' Builds the info response for the specified user. Args: user_obj: The object representation for the specified user Returns: The Python dictionary that can be converted to JSON and sent as a response. ''' # get the state of the user state = user_session.get_state(user_obj.uuid) # create the attachment contents = {} contents['title'] = COMPANY_NAME contents['title_link'] = COMPANY_URL # color the attachment based off of state if state == 'ONLINE': contents['color'] = "good" elif state == 'OFFLINE': contents['color'] = "danger" elif state == 'PAUSED': contents['color'] = "warning" # Determine the text of the attachment contents['text'] = 'Your current state is ' + str(state) + '.' if state == 'ONLINE' or state == 'PAUSED': work_time = user_session.get_work_time(user_obj.uuid) # build the hours fields = [] f1 = {} f1['title'] = 'Worked Time (session)' f1['value'] = '%.2f' % (work_time / 3600000.0) f1['short'] = True f2 = {} f2['title'] = 'Total Hours (month)' f2['value'] = user_session.get_total_worked(user_obj.uuid) f2['short'] = True fields.append(f1) fields.append(f2) contents['fields'] = fields elif state == 'OFFLINE': # build the hours fields = [] f1 = {} f1['title'] = 'Total Hours (month)' f1['value'] = user_session.get_total_worked(user_obj.uuid) f1['short'] = True f2 = {} f2['title'] = 'Goal Hours (month)' f2['value'] = user.get_goal_total(user_obj.uuid) f2['short'] = True fields.append(f1) fields.append(f2) contents['fields'] = fields # attach the footer _attach_footer(contents) # construct the response message with the attachment message = slack_api.Message() message.add_attachment(contents) return message.get_contents()
def work(self): ''' This pulse works, serving the users, incrementing their times. ''' # get the current time curr_time = time.time() if curr_time - self.credit_event > WORK_INTERVAL: # amount of milliseconds to credit to everyone working credit_amount = int((curr_time - self.credit_event) * 1000) # update timestamp for last time we credited self.credit_event = curr_time # load all users from db, if they dont exist in hash yet self.load_users() for key in self.users: user_obj = self.users[key] # get the state of the user state = user_session.get_state(user_obj.uuid) if state == 'ONLINE': # update in the db their work time user_session.update_work_time(user_obj.uuid, credit_amount) user_obj.work_time_ms = user_obj.work_time_ms + credit_amount # every hour notify them of how long they've worked hours_worked = int(user_obj.work_time_ms / 3600000) if hours_worked >= 1: # when did we last notify them about their time if user_obj.notify_hour < hours_worked: user_obj.notify_hour = user_obj.notify_hour + 1 # send slack message to channel slack_server.send_message( contents='You have been working for ' + str(hours_worked) + ' hours this session.', channel='@' + str(user_obj.username), username='******', icon_emoji=':loudspeaker:') # reset the pause time user_obj.pause_time_ms = 0 elif state == 'PAUSED': user_obj.pause_time_ms = user_obj.pause_time_ms + credit_amount # if 15 minutes have passed, send slack notification if user_obj.pause_time_ms > 15 * 60 * 1000: user_obj.pause_time_ms = 0 # send slack message to channel slack_server.send_message( contents= 'You have been idle/paused for 15 minutes. When you get back please use `/epoch resume`.', channel='@' + str(user_obj.username), username='******', icon_emoji=':loudspeaker:') elif state == 'OFFLINE': # reset their work time user_obj.work_time_ms = 0 user_obj.pause_time_ms = 0 user_obj.notify_hour = 0