def create_many(self): # There should be four digests: two users by two digest types. user1 = User.create(name='User One', email='*****@*****.**') user2 = User.create(name='User Two', email='*****@*****.**') User.put_multi([user1, user2]) report_params = {'context_name': 'Geography', 'program_name': 'Foo'} notes = [ self.test_create(user=user1, note_type='generic'), self.test_create(user=user1, note_type='generic'), self.test_create(user=user1, note_type='report', template_params=report_params), self.test_create(user=user1, note_type='report', template_params=report_params), self.test_create(user=user2, note_type='generic'), self.test_create(user=user2, note_type='generic'), self.test_create(user=user2, note_type='report', template_params=report_params), self.test_create(user=user2, note_type='report', template_params=report_params), ] Notification.put_multi(notes) return user1, user2, notes
def post(self): json_data = request.get_json(force=True) header = request.headers["Authorization"] if not json_data: return {'message': 'No input data provided'}, 400 if not header: return {"Messege": "No api key!"}, 401 else: user = User.query.filter_by(api_key=header).first() if not user: return {'message': 'User ID not available'}, 402 accepted_order = Accepted_Order.query.filter_by( order_id=json_data['order_id']).first() if not accepted_order: return {'message': 'order ID not available'}, 403 user = User.query.filter_by(user_id=json_data['user_id']).first() notification = Notification( user_id=json_data['user_id'], order_id=json_data['order_id'], notification_content=json_data['notification_content'], driver_mode=user.driver_mode) db.session.add(notification) db.session.commit() result = Notification.serialize(notification) return {"status": 'success', 'data': result}, 201
def changed_project_task(user, project, task, project_cohort_id=None): """If change made by an org admin, notify related account manager, or all the program owners. Otherwise, notify project liaison, or all the org admins. """ t_dict = task.to_client_dict() program_config = Program.get_config(project.program_label) if project_cohort_id: link = '/dashboard/{pc}/tasks/{ckpt}/{task}'.format( pc=DatastoreModel.convert_uid(project_cohort_id), ckpt=DatastoreModel.convert_uid(task.checkpoint_id), task=task.uid ) else: link = '/dashboard' params = { 'task_id': task.uid, 'context_id': project.uid, 'subject': "Task updated", 'body': u"{} updated \"{}\" in {}.".format( user.name, t_dict['name'], program_config['name']), 'link': link, 'autodismiss': True, } if user.non_admin: # Send to account managers (usu. set via program config -> # default_account_manager). parents = get_project_program_recipients(project) else: parents = get_project_organization_recipients(project) notes = [Notification.create(parent=p, **params) for p in parents] filtered_notes = Notification.filter_redundant(notes) ndb.put_multi(filtered_notes)
def test_get_day(self): """Get all user's notifications for the last 24 hours.""" user = User.create(name='superdude', email='*****@*****.**') old = self.test_create(user=user) old.created = datetime.datetime(2017, 1, 1) # Simulate a put, but without stripping timestamps at this step, which # SqlModel.put() would normally do. This lets us post-date the # notification. row_dict = Notification.coerce_row_dict(old.to_dict()) with mysql_connection.connect() as sql: sql.insert_or_update(Notification.table, row_dict) # This one gets CURRENT_TIMESTAMP, as normal. new = self.test_create(user=user) new.put() # Only the new one should be returned. start = datetime.datetime.now() - datetime.timedelta(hours=12) end = datetime.datetime.now() + datetime.timedelta(hours=12) notes = Notification.get_period_for_user( user, util.datelike_to_iso_string(start), util.datelike_to_iso_string(end), ) self.assertEquals(len(notes), 1)
def new_message(app, user, level, text): newNotif = Notification() newNotif.app = app newNotif.user = user newNotif.level = level newNotif.text = text #newNotif.actions = actions #newNotif.save() session.commit() return newNotif
def send_notifications(): try: context = {} with create_session() as s: last_notification_sent = s.query(Notification).order_by( Notification.id.desc()).first() last_timestamp = float(last_notification_sent.created_at_utc ) if last_notification_sent else -1 logging.warning('last sent at %s' % last_timestamp) for user in l._get_users(s): try: context[user.id] = {} total_num_of_reviews = 0 for design in user.designs: if len(design.reviews) > 0: context[user.id][design.uri] = { 'name': design.description, 'reviews': [] } for review in design.reviews: if float(review.created_at_utc ) > last_timestamp: new_review = { 'body': review.body, 'timestamp': utils.epoch_to_datetime_string( review.created_at_utc) } context[user.id][design.uri][ 'reviews'].append(new_review) total_num_of_reviews = total_num_of_reviews + 1 if total_num_of_reviews: subject = 'A summary of your recent design submissions' body = emailer.new_review_template.render( designs_dict=context[user.id]) receivers = [user.email] emailer.send_html(receivers, subject, body) logging.warning('sent on user %s with email %s' % (user.id, user.email)) else: logging.warning( 'no new reviews on user %s, skip sending email' % user.id) except: logging.warning('hey user %s email failed' % user.email) o = Notification() o.updated_at_utc = time.time() s.add(o) except Exception as e: logging.warning(e) return 'Failed'
def create_notification(self, *args, **kwargs): ''' Usage: createNotification(cur_user = '******', form = 'Post form') Post form: {title: 'Your title', content: 'Your content', groups: "['groupA', 'groupB']"} ''' form = kwargs['form'] notify = Notification(form['title'], form['content']) group_names = form.getlist('groups') db.session.add(notify) db.session.commit() # groups = json.loads(form['groups']) # for group_name in groups: if 'all' in group_names: group_names = ['all'] for group_name in group_names: if group_name == 'none': continue notify_groups = NotificationGroups(notify.id, group_name) db.session.add(notify_groups) db.session.commit() if 'sendMail' in form: self.mail_notification(notify.id) users = User.query.all() for user in users: user_group = user.user_group for group_name in group_names: if user_group == group_name: tempPair = UserNotificationPair(user.username, notify.id) db.session.add(tempPair) break db.session.commit() return {"success": 'true'}
def joined_cohort(user, project_cohort): """Notify program and super admins.""" # This always happens along with creating a program. pc = project_cohort program_admins = User.get(owned_programs=pc.program_label) super_admins = User.get(user_type='super_admin') organization = Organization.get_by_id(pc.organization_id) program_config = Program.get_config(pc.program_label) cohort_name = program_config['cohorts'][pc.cohort_label]['name'] notes = [] for admin in program_admins + super_admins: note = Notification.create( parent=admin, context_id=pc.uid, subject=u"{org} joined a cohort".format(org=organization.name), body=( u"{org} joined {cohort} in {program}. The organization is " "currently {status}." ).format( org=organization.name, cohort=cohort_name, program=program_config['name'], status=organization.status, ), link='/organizations/{}'.format(organization.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def release_and_notify(self, week): # Update all reports for a given week and set preview = False, _and_ # create notifications for all related users. # Capture which reports are previews before we release them. We'll base # the notifications on this list to make sure we're not notifying about # any reports that aren't previews. reports_to_release = Report.get_previews(week) # This is the "release" part. num_reports_released = Report.release_previews(week) # Now we have to load a bunch of data from the related teams, # classrooms, and users in order to create notifications. if len(reports_to_release) != num_reports_released: logging.error( "Report.get_previews() ({}) and Report.release_previews() " "({}) didn't hit the same number of rows.".format( len(reports_to_release), num_reports_released)) team_ids = {r.team_id for r in reports_to_release} classroom_ids = { r.classroom_id for r in reports_to_release if r.classroom_id } # Load all related teams and classrooms as a batch. teams = Team.get_by_id(team_ids) classrooms = Classroom.get_by_id(classroom_ids) t_index = {t.uid: t for t in teams} c_index = {c.uid: c for c in classrooms} p_index = {p.uid: p for p in Program.get()} notes = [] for r in reports_to_release: team = t_index.get(r.team_id) program = p_index.get(team.program_id) classroom = c_index.get(r.classroom_id, None) result = self.notify_for_single_report(program, team, classroom) # result might be a list or None if result: notes += result Notification.put_multi(notes) return num_reports_released
def create_notification(name, user_id, payload_json): """Create and return a notification.""" n = Notification(name=name, user_id=user_id, payload_json=payload_json) db.session.add(n) db.session.commit() return n
def test_users_with_notifications(self): user1, user2, notes = self.create_many() start = datetime.datetime.now() - datetime.timedelta(hours=12) end = datetime.datetime.now() + datetime.timedelta(hours=12) user_ids = Notification.users_with_notifications( util.datelike_to_iso_string(start), util.datelike_to_iso_string(end), ) self.assertEqual({user1.uid, user2.uid}, set(user_ids))
def set_up(self): # Let ConsistencyTestCase set up the datastore testing stub. super(TestNotifications, self).set_up() with mysql_connection.connect() as sql: sql.reset({ 'digest': Digest.get_table_definition(), 'notification': Notification.get_table_definition(), 'user': User.get_table_definition(), })
def add_notification(user_id, notification_type): """Adds a notification to the db, which will then later be used by AJAX to display notifications to the user""" notification = Notification(user_id=user_id, notification_type=notification_type, added_at=datetime.now()) db.session.add(notification) db.session.commit() return notification.notification_id
def received_invitation(user, inviter, context_id=None): note = Notification.create( parent=user, context_id=context_id, subject="You've been invited to PERTS.", body=u"{} invited you to create an account.".format(inviter.name), link='/dashboard', autodismiss=True, ) note.put()
def received_data_request(user, data_request): """Notify just recipient.""" note = Notification.create( parent=user, context_id=data_request.uid, subject=data_request.title, body=data_request.description, # obv. needs to be extended later link=data_request.link, ) note.put()
def joined_organization(approver, joiner, organization): """Notify joiner that existing owners approved the join.""" note = Notification.create( parent=joiner, context_id=organization.uid, subject="You have been approved", body=u"{} approved you to join {}.".format( approver.name, organization.name), link='/organizations/{}'.format(organization.uid), autodismiss=True, ) note.put()
async def update_time_step2(message: types.Message, state: FSMContext): birthday = db.query(Notification).filter(Notification.chat_id == message.chat.id).first() if birthday is None: notification = Notification(chat_id=message.chat.id, time=message.text) db.add(notification) db.commit() else: db.query(Notification).filter(Notification.chat_id == message.chat.id).update({'time': message.text}) db.commit() await state.finish()
def changed_organization_task(user, organization, task, project_cohort_id=None): """Notify the other type of user, not one's own type: org or super.""" t_dict = task.to_client_dict() if project_cohort_id: link = '/dashboard/{pc}/tasks/{ckpt}/{task}'.format( pc=DatastoreModel.convert_uid(project_cohort_id), ckpt=DatastoreModel.convert_uid(task.checkpoint_id), task=task.uid ) else: link = '/dashboard' params = { 'task_id': task.uid, 'context_id': organization.uid, 'subject': "Task updated", 'body': u"{} updated \"{}\" in {}.".format( user.name, t_dict['name'], organization.name), 'link': link, 'autodismiss': True, } notes = [] if user.super_admin: # Notify anyone who owns the organization. admins = User.get( user_type='user', owned_organizations=organization.uid) notes += [Notification.create(parent=a, **params) for a in admins] if user.non_admin: # Super admins are too busy to care. pass # # Old code for sending to supers. # supers = User.get(user_type='super_admin') # notes += [Notification.create(parent=s, **params) for s in supers] # else program admin? Program admins are largely not implemented, and likely # won't have rights to modify/approve organizations anyway. filtered_notes = Notification.filter_redundant(notes) ndb.put_multi(filtered_notes)
def is_resource_available(student, _class, image, start_time, reservation_length): db = Session() if len(nova.servers.list()) >= MAX_INSTANCES: notification = Notification(user_id=student.id, \ message='Too many instances running to start a new reservation', \ status="ERROR") db.add(notification) db.commit() return False return True
def test_create(self, user=None, note_type='generic', template_params={}): params = { 'url': 'http://www.example.com', 'message': "Single item goes here.", 'first_name': "Henry", 'program_name': "Foo Program", } params.update(**template_params) n = Notification.create( user_id=user.uid if user else 'User_foo', type=note_type, template_params=params, ) return n
def rejected_from_organization(rejecter, rejectee, organization): """Notify rejectee that existing owners rejected them.""" note = Notification.create( parent=rejectee, context_id=organization.uid, subject="You were not admitted", body=u"{} rejected your request to join {}.".format( rejecter.name, organization.name), # Doesn't make sense to send them to an org page which they're not # permitted to access. Provide no link at all. autodismiss=True, viewable=False, ) note.put()
def post(self): json_data = request.get_json(force=True) if not json_data: return {'message': 'No input data provided'}, 400 notification = Notification.query.filter_by( notification_id=json_data['notification_id']).first() if not Notification: return {'message': 'Notification id not available'}, 400 notification.status = True db.session.commit() result = Notification.serialize(notification) return {"status": 'success', 'data': result}, 201
def requested_to_join_organization(user, organization): """Notify existing org admins.""" # Joining user won't appear here b/c they have assc_organizations. owners = User.get(owned_organizations=organization.uid, n=float('inf')) notes = [] for owner in owners: note = Notification.create( parent=owner, context_id=organization.uid, subject="New user in your organization", body=u"{} would like to join {}.".format( user.name, organization.name), link='/organizations/{}/users'.format(organization.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def notify_for_single_report(self, program, team, classroom=None): """Notifications for class contact or all members re: one report.""" if not team.report_reminders: logging.info( "{} has report reminders disabled; not notifying".format( team.uid)) return if classroom: recipients = [User.get_by_id(classroom.contact_id)] else: recipients = User.query_by_team(team.uid) protocol = 'http' if util.is_localhost() else 'https' # Note that reports are hosted by the local _backend_ gae sdk, not the # react-app dev server on :3000. But for now we're just pointing to the # list of a team's reports, which _is_ on :3000. domain = ('localhost:3000' if util.is_localhost() else os.environ['HOSTING_DOMAIN']) reports_page = '{}://{}/teams/{}/reports'.format( protocol, domain, team.short_uid) # If we do want to link directly to the report, we'll have to wrestle # with authentication and what that looks like. We can either generate # a token right here (but that would be the link was shareable, and it # would expire, both of which seem wrong) or build some additional # client code that would know how to redirect an unauthed user to # login and back. notes = [] for user in recipients: notes.append( Notification.create( user_id=user.uid, type='report', template_params={ 'context_name': classroom.name if classroom else team.name, 'first_name': user.first_name, 'program_name': program.name, 'url': reports_page, })) return notes
def get(self): # Takes query string param `today`, which defaults to a date string for # today, if today is a Monday, else next Monday. start = self.request.get('start', None) end = self.request.get('end', None) # What time period is of interest? if start and end: # Make sure inputs are formatted correctly datetime.datetime.strptime(start, config.iso_datetime_format) datetime.datetime.strptime(end, config.iso_datetime_format) if start > end: raise Exception("DigestNotifications requires end > start.") logging.info("Received custom start and end times: {} - {}".format( start, end)) else: # most recent midnight, pacific standard time today = datetime.date.today() end = datetime.datetime(today.year, today.month, today.day, 8) start = end - datetime.timedelta(hours=24) # from here forward we'll work in ISO 8601 strings. start = util.datelike_to_iso_string(start) end = util.datelike_to_iso_string(end) logging.info("Using default start and end times: {} - {}".format( start, end)) user_ids = Notification.users_with_notifications(start, end) # Launch a task to process each user. This way we can handle arbitrary # growth in the number of users without worrying about time or memory # limits, assuming number of notifications per user is fairly constant. for id in user_ids: taskqueue.add( url='/task/{}/digest_notifications'.format(id), params={ 'start': start, 'end': end }, queue_name='default', ) logging.info(user_ids) self.response.write(json.dumps({'user_ids': user_ids}))
def create_notification(self, *args, **kwargs): ''' Usage: createNotification(cur_user = '******', form = 'Post form') Post form: {title: 'Your title', content: 'Your content', groups: "['groupA', 'groupB']"} ''' form = kwargs['form'] notify = Notification(form['title'], form['content']) group_names = form.getlist('groups') db.session.add(notify) db.session.commit() # groups = json.loads(form['groups']) # for group_name in groups: if 'all' in group_names: group_names = ['all'] for group_name in group_names: if group_name == 'none': continue notify_groups = NotificationGroups(notify.id, group_name) db.session.add(notify_groups) db.session.commit() return {"success": 'true'}
def downloaded_identifiers(user, project_cohort_id): supers = User.get(user_type='super_admin') notes = [] project_cohort = ProjectCohort.get_by_id(project_cohort_id) organization = Organization.get_by_id(project_cohort.organization_id) program = Program.get_config(project_cohort.program_label) cohort_name = program['cohorts'][project_cohort.cohort_label]['name'] for sup in supers: note = Notification.create( parent=sup, context_id=project_cohort_id, subject="IDs Downloaded", body=u"{} ({}) downloaded IDs for {}: {} {}.".format( user.name, user.email, organization.name, program['name'], cohort_name), link='/dashboard/{}'.format(project_cohort.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def send_notification(users, notification_title="Desconocido", notification_body="Desconocido", id_notification_type=ID_NOTIFICATION_TYPE_OTHERS, notification_picture="Desconocido", read=False, visible=True, notification_type=None): push_notification_service = FCMNotification( api_key=DBSettings.FIREBASE_API_KEY) notifications = [] for id_user in users: notification = Notification( notification_title=notification_title, notification_body=notification_body, read=read, visible=visible, notification_datetime=datetime.datetime.now(), id_notification_type=id_notification_type, id_user=id_user, notification_picture=notification_picture) notifications.append(notification) try: db.session.add_all(notifications) db.session.commit() except Exception as e: db.session.rollback() devices = Device.query.filter(Device.id_user.in_(users)).all() if len(devices) > 0: data_message = {"notification_type": notification_type} registration_ids = [device.registration_id for device in devices] push_notification_service.notify_multiple_devices( registration_ids=registration_ids, message_title=notification_title, message_body=notification_body, extra_kwargs={"id_notification_type": id_notification_type}, click_action="FCM_PLUGIN_ACTIVITY", data_message=data_message)
def test_get_notifications(self): user = User.create(email='*****@*****.**') user.put() admin = User.create(email='*****@*****.**', user_type='super_admin') admin.put() notes = [ Notification.create( # intentionally created in reverse time order, to demonstrate # that we can query them in correct time order. created=datetime.datetime(2018, 8, 10 + x), parent=user, context_id='Org_foo', subject='Thing one.', body='The thing is thingish.', link='/organizations/foo', ) for x in range(3) ] ndb.put_multi(notes) user_response = self.testapp.get( '/api/users/{}/notifications?dismissed=false'.format(user.uid), headers=login_headers(user.uid), ) admin_response = self.testapp.get( '/api/notifications?dismissed=false', headers=login_headers(admin.uid), ) # All responses should be ordered with newest first by default. for response in (user_response, admin_response): response_notes = json.loads(response.body) previous_time = response_notes[0]['created'] for note_dict in response_notes[1:]: self.assertLess(note_dict['created'], previous_time) previous_time = note_dict['created']
def add_reservation_jobs(student, reservation, start_time, reservation_length, image, db): # Add 30 seconds onto start_time start_time = start_time + datetime.timedelta(seconds=30) # Check instance at start time + 2 minutes check_time = start_time + datetime.timedelta(seconds=120) # Use seconds instead of hours for stop time (don't think minutes are an option) reservation_length_in_seconds = 60 * 60 * int(reservation_length) # Kill the instance at start_time + x hours stop_time = start_time + datetime.timedelta( seconds=reservation_length_in_seconds) # Warn time is stop_time - 5 minutes (or 300 seconds) warn_time = start_time + datetime.timedelta( seconds=reservation_length_in_seconds - 300) # 1) Start the instance start_instance_job = start_instance.apply_async([reservation.id], eta=start_time) reservation.start_instance_job = start_instance_job.id notification = Notification(user_id=student.id, message='Instance for reservation ' + str(reservation.id) + ' will start at ' + str(start_time), status="INFO") db.add(notification) db.commit() # 2) Make sure the instance is in a good state check_instance_job = check_instance.apply_async([reservation.id], eta=check_time) reservation.check_instance_job = check_instance_job.id notification = Notification(user_id=student.id, message='Instance for reservation ' + str(reservation.id) + ' will be checked at ' + str(check_time), status="INFO") db.add(notification) db.commit() # 3) Setup a job to warn the user 5 minutes before the instance is destroyed warn_reservation_ending_job = warn_reservation_ending.apply_async( [reservation.id], eta=warn_time) reservation.warn_reservation_ending_job = warn_reservation_ending_job.id notification = Notification(user_id=student.id, message='User with reservation ' + str(reservation.id) + ' will be warned at ' + str(warn_time), status="INFO") db.add(notification) db.commit() # 4) Finally destroy the instance # - XXX FIX ME XXX Note this job needs the db to delete the reservation as well stop_instance_job = stop_instance.apply_async([reservation.id], eta=stop_time) reservation.stop_instance_job = stop_instance_job.id notification = Notification(user_id=student.id, message='Instance for reservation ' + str(reservation.id) + ' will stop at ' + str(stop_time), status="INFO") db.add(notification) db.commit() return True
def test_get(self): n = self.test_create() n.put() self.assertEqual(n, Notification.get_by_id(n.uid)) return n