def api_create_note(**kwargs): data = json.loads(request.data) if request.data else {} bapi = BullhornApi() action = data['action'] comments = data['comments'] candidate_id = data['candidateId'] try: note_id = bapi.create_note(action=action, comments=comments, candidate_id=candidate_id) if note_id: _log('++ created note: {}'.format(note_id)) to_return = { 'success': True, 'note_id': note_id, } else: to_return = { 'success': False, 'message': 'API error' } except Exception as e: _capture_exception(e) to_return = { 'success': False, 'message': 'API error' } response = jsonify(to_return) response.status_code = 200 return response
def send_password_reset(user): """ helper function which sends a password reset email to the inputted user :param user: User object to send an email to :return: None """ _log('++ sending password reset email for: {} {}'.format( user.first_name, user.last_name)) secret_string = ''.join( random.choice(string.ascii_lowercase + string.digits) for _ in range(20)) # if local set the domain to localhost if ENV_DICT['ENVIRON'] == 'LOCAL': secret_link = 'http://localhost:8080/reset/{}/'.format(secret_string) # otherwise use the subdomain of the tenancy else: secret_link = 'http://{}.cpisearch.io/reset/{}/'.format( user.tenancy, secret_string) reset_link_object = PasswordResetLink( user_id=user.user_id, secret_link=secret_string, tenancy=user.tenancy, ) db.session.add(reset_link_object) db.session.commit() send_email(to_email=user.email, subject='SuccessKit Password Reset', template_path='emails/password_reset_email.html', template_vars={ 'user': user, 'secret_link': secret_link })
def tumblr_post_img(text): img_match = re.search('img:(.*)\n', text) if img_match: _log('++ saving image to tumblr', debug=True) url = img_match.group(1) note_text = strip_data(text) post_photo_to_tumblr(photo_url=url, caption=note_text)
def create_note(self, comments, action, candidate_id, author_email=None): """ creates a note with inputted fields :param comments: text of the note :param action: coded string of type of note :param candidate_id: string bullhorn id of the candidate the note should be added to :param author_email: string email address of the recruiter that should be listed as the author :return: note object """ note_args = { 'action': action, 'comments': comments, 'personReference': { '_subtype': 'Candidate', 'id': candidate_id } } if author_email: corp_users = self.query_corporate_user(author_email) if corp_users: corp_user = corp_users[0] note_args['commentingPerson'] = { '_subtype': 'CorporateUser', 'id': corp_user['id'] } else: _log('++ failed to find corporate user with email: {}'.format( author_email)) returned = self.create_entity('Note', note_args) if returned['changeType'] == 'INSERT': return returned['changedEntityId'] else: raise Exception('++ failed to create note: {}'.format( json.dumps(returned)))
def flask_email_test(): """ this helper page for testing if email sending is working """ _log('++ sending test email') send_test_email(ENV_DICT['MAIL_DEFAULT_SENDER']) return 'email test'
def save_simplenote(note_text, tags=None): if not tags: tags = [] new_note = snote.add_note({ 'content': note_text.encode('ascii', 'ignore'), 'tags': tags })[0] _log('++ new simplenote: {}'.format(new_note['key'])) return new_note
def error_handler_500(e): """ if a page throws an error, log the error to slack, and then re-raise the error """ exc_type, exc_value, exc_traceback = sys.exc_info() formatted_lines = traceback.format_exc() _log('@channel: 500 error: {}'.format(e.message)) _log(formatted_lines) raise e
def scrape_rooms(db_session): building_links = get_list_of_building_links() for b_link in building_links: _log('++ getting floorplans from {}'.format(b_link)) floorplan_links = get_list_of_floorplan_links_from_building(building_link=b_link) for f_link in floorplan_links: save_room( building_link=b_link, floorplan_image_link=f_link, db_session=db_session )
def post_photo_to_tumblr(photo_url, caption, tumblr='memecollections.tumblr.com'): photo_url = photo_url.strip() # if a dropbox image, fetch it to a temp file, and then post it if photo_url.startswith('https://www.dropbox.com/s/'): temp_path = fetch_screenshot(screenshot_url=photo_url) created = client.create_photo(tumblr, caption=caption, state="published", data=[temp_path]) os.system('rm {}'.format(temp_path)) # if a public image else: created = client.create_photo(tumblr, caption=caption, state="published", source=photo_url) # log the new post post_url = 'http://{tumblr}/image/{id}'.format( tumblr=tumblr, id=created['id'] ) _log('++ new tumblr post: {}'.format(post_url))
def process_note(text, title): # get commands commands = get_commands(text) _log('++ found commands: {}'.format(str(commands)), debug=True) # trigger actions based on certain commands if 'meme' in commands: tumblr_post_img(text) # get hashtags hashtags = list(get_hashtags(text)) _log('++ found hashtags: {}'.format(str(hashtags)), debug=True) # use a hashtag as an evernote notebook name if not hashtags: notebook_name = 'as4' else: notebook_name = hashtags[0] # save a simplenote # save_simplenote_helper(text=text, hashtags=hashtags) # save an evernote note_text = evernote_format_text(text=text, hashtags=hashtags, title=title) save_evernote(note_title=title, note_text=note_text, notebook_name=notebook_name)
def save_note_endpoint(): text = request.form['text'] text += ' ' note_text = strip_data(text) note_text_lines = note_text.split('\n') title = '' # quick loop to find first non blank line, and use that as title for line in note_text_lines: if line: title = line break # strip special char from title stripped_title = title.replace(' ', '_') stripped_title = re.sub(r'[\W]+', '', stripped_title) # save note to dropbox and log note to slack save_note_to_dropbox(title=stripped_title, text=text) _log('++ saved note: {}'.format(stripped_title)) _log('++: {title}\n{text}'.format(title=title, text=text), channel_id=NOTES_CHANNEL) # process note and initiate functions based on hashtags process_note(text=text, title=title) return 'saved'
def check_for_ps1(self): access_token = SECRETS_DICT['FB_FRIENDSFRIENDS_ACCESS_TOKEN'] url = "https://graph.facebook.com/{}/feed?access_token={}".format(self.fb_event_id, access_token) req = urllib2.Request(url) response = urllib2.urlopen(req) the_page = response.read() returned = json.loads(the_page) messages = returned['data'] # also check for mo recent date previous_latest_date_string = self.get_latest_alert_date() if not previous_latest_date_string: first_date_string = messages[0]['created_time'] self.save_latest_alert_date(date_string=first_date_string) previous_latest_date = numpy.datetime64(previous_latest_date_string) latest_found = previous_latest_date for message in messages: updated_time_string = message.get('created_time') if updated_time_string: message_date = numpy.datetime64(updated_time_string) if previous_latest_date == numpy.datetime64('NaT') or message_date > previous_latest_date: if latest_found == numpy.datetime64('NaT') or message_date > latest_found: latest_found = message_date self.save_latest_alert_date(date_string=updated_time_string) message_text = message.get('message') if message.get('message') else '' message_id = message['id'] link_to_comment = 'http://facebook.com/{}/'.format(message_id) message_text += '--> {}'.format(link_to_comment) already_sent = self.db_session.query(KeyVal).filter(KeyVal.key == self.sent_alert_key, KeyVal.value == message_id) if not already_sent.count(): already_sent = KeyVal(key=self.sent_alert_key, value=message_id) self.db_session.add(already_sent) self.db_session.commit() _log('++ sending text to {phone_number}: {msg}'.format( phone_number=self.to_phone_number, msg=message_text.encode('ascii', 'ignore') )) send_text(msg=message_text, to_phone_number=self.to_phone_number)
def save_evernote(note_title, note_text, notebook_name): _log('++ saving evernote: {}'.format(note_title), debug=True) # strip title note_title = note_title.strip() # first get the notebook guid notebook_guid = get_or_create_notebook(name=notebook_name) # find links in the note, and replaces with a urlfinder = re.compile("(http\S+)") note_text = urlfinder.sub(r'<a href="\1">\1</a>', note_text) # wrap newlines in div note_text = '<div>{}</div>'.format(note_text) note_text = note_text.replace('\n', '<br></br>') # then create the note noteStore = client.get_note_store() note = Types.Note() note.title = note_title note.content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">' note.content += '<en-note>{note_text}</en-note>'.format(note_text=note_text) note.notebookGuid = notebook_guid note = noteStore.createNote(note) _log('++ new evernote note: https://www.evernote.com/Home.action#n={}'.format(note.guid)) return note.guid
def truncate_email(email_content): """ helper function which strips email_content down to just the actual message sent (not including replies and other things) :param email_content: string contents of email :return: truncated string contents of email """ # first try removing any lines = email_content.split('\n') keep_lines = [] found_reply = False for index in range(0, len(lines)): line = lines[index] m = re.match('>> On.*at.* wrote:', line) if m: test_line = lines[index + 2] if test_line.startswith('>>>'): _log('++ truncating email at line "{}"'.format(line)) keep_lines.append(line) keep_lines.append('... truncated') found_reply = True break # if we made it here, then just keep going keep_lines.append(line) # combine keep_lines to_return = '\n'.join(keep_lines) # if we didn't already truncate, then just truncate to first 3000 characters if not found_reply: if len(to_return) > 3000: to_return = to_return[:3000] to_return += '.... truncated after 3000 char' # return whatever we have return to_return
def create_app(): # log some basic things about startup and which environment we're in if ENV_DICT['ENVIRON'] == 'PROD': _log('++ USING PROD DATABASE') else: _log('++ using environ: {}'.format(ENV_DICT['ENVIRON'])) # create the flask app app = Flask(__name__, template_folder=TEMPLATE_DIR, static_folder=BACKEND_PATH) app.config.update(DEBUG=ENV_DICT.get('FLASK_DEBUG') or False, SECRET_KEY=ENV_DICT['FLASK_SECRET_KEY']) # initialize sql alchemy app.config['SQLALCHEMY_DATABASE_URI'] = get_db_url() db.init_app(app) # BasicAuth for flask_admin app.config['BASIC_AUTH_USERNAME'] = ENV_DICT['BASIC_AUTH_USERNAME'] app.config['BASIC_AUTH_PASSWORD'] = ENV_DICT['BASIC_AUTH_PASSWORD'] basic_auth.init_app(app) # initialize flask-admin admin = get_flask_admin() admin.init_app(app) # initialize flask-mail mail_keys = [ "MAIL_SERVER", "MAIL_PORT", "MAIL_USE_TLS", "MAIL_USERNAME", "MAIL_PASSWORD", "MAIL_DEFAULT_SENDER" ] for key in mail_keys: app.config[key] = ENV_DICT[key] mail.init_app(app) # register blueprints app.register_blueprint(get_hello_helpers_blueprint()) app.register_blueprint(get_auth_blueprint()) app.register_blueprint(get_bh_blueprint()) app.register_blueprint(get_webhook_blueprint()) # configure sentry if ENV_DICT.get('SENTRY_DSN'): _log('++ using Sentry for error logging') sentry.init_app(app, dsn=ENV_DICT['SENTRY_DSN']) @app.route("/api/hello/") def hello_page(): return render_template("hello.html") @app.teardown_appcontext def shutdown_session(exception=None): db.session.remove() @app.errorhandler(Exception) def error_handler(e): """ if a page throws an error, log the error to slack, and then re-raise the error """ _capture_exception(e) # re-raise error raise e # return the app return app
def flask_slack_test(): """ this helper page for testing if slack is working """ _log('@channel: slack is working?') return 'slack test'
def api_email_webhook(**kwargs): """ endpoint to post emails to (via zapier integration) """ api_key = request.headers.get('CPI-API-KEY', None) if not api_key == ENV_DICT['CPI_API_KEY']: raise Exception('++ email webhook with bad api key') # should we save the date of last-response # whether this key is set in the header or not is configured within zapier for a particular email address save_last_response = request.headers.get('LAST-RESPONSE', None) == '1' data = request.form to_email = data['raw__To_email'] # recipient_email = data['recipient'] ## this just contains the bcc from_email = data['from_email'] email_content = data['body_plain'] subject = data['subject'] # truncate the email (to avoid replies showing up as part of the email content) note_content = truncate_email(email_content) # log message _log( '++ received web hook with data. to_email: {to_email} | subject: {subject} | save_last_response: {save_last_response}' .format( to_email=to_email, subject=subject, save_last_response=save_last_response, )) # attempt to create note bapi = BullhornApi() # create the note search_results = bapi.search_candidates( input=to_email, fields='email,id,firstName,lastName') error_msg = None if search_results: candidate = search_results[0] if candidate['email'] == to_email: # if save_last_response, then update the save_last_response field of this candidate if save_last_response: try: bapi.save_last_response(candidate['id']) except: _log('++ failed to update last_response_date for {}'. format(to_email)) # then also create the note for this user note_id = bapi.create_note( comments=note_content, action='Email sent', candidate_id=candidate['id'], author_email=from_email, ) _log('++ created note via email: {}'.format(note_id)) if note_id: response = jsonify({ 'success': 'True', 'message': 'created note' }) response.status_code = 200 return response else: error_msg = 'Failed to create note for candidate'.format( to_email) else: error_msg = 'Search found candidate with non-matching email {}'.format( candidate['email']) else: error_msg = 'Failed to find candidate in bullhorn with email'.format( to_email) # if we reached here, then a note was not created, and we should send an error email _log('++ note creation failure for email sent to {}. With error: {}'. format(to_email, error_msg)) alert_email_set = set(ENV_DICT['ALERT_EMAILS']) alert_email_set.add(from_email) for alert_email in alert_email_set: t_vars = { 'email_content': email_content, 'to_email': to_email, 'subject': subject, 'error_msg': error_msg, } send_email(to_email=alert_email, subject='Note Creation Failure', template_path='emails/alert_email.html', template_vars=t_vars) response = jsonify({ 'success': 'False', 'message': 'failed to created note' }) response.status_code = 200 return response
def activate_account_api(): """ endpoint to activate a user's account by looking for a matching activation link """ # get the data for this query data = request.get_json() if not data: response = jsonify({ 'success': False, 'message': 'Missing request body' }) response.status_code = 422 return response # process arguments arg_email = data.get('email').strip().lower() # check if there is a user with this activation_link secret_link = data.get('secret_link') user = db.session.query(User).filter( User.activation_link == secret_link, ).one_or_none() if not user: response = jsonify({ 'success': False, 'message': 'This activation link is no longer active. Contact your system administrator to receive a new one.' }) response.status_code = 200 return response # check if this user has already activated their account if user.activated: response = jsonify({ 'success': False, 'message': 'This account has already been activated. Try forgot password to recover your password.' }) response.status_code = 200 return response # check if the correct email address was supplied if user.email != arg_email: response = jsonify({ 'success': False, 'message': 'This is not the correct email for this activation link. Contact your system administrator to request a link for this email.' }) response.status_code = 200 return response # generate and set new password new_password = generate_password_hash(data.get('password')) user.password = new_password user.activated = True db.session.add(user) db.session.commit() # log that a user just activated their account _log('++ {} just activated their account'.format(user.email), '_signup') # return authenticated token token = generate_auth_token(user_id=user.user_id) response = jsonify({'success': True, 'token': token}) response.status_code = 200 return response
def prog1_page(): question_text = request.form.get('questionText') _log('question text: {}'.format(question_text)) # printer1(question_text) return render_template("ty.html")