def _update_service_friends(friend_service_identity_connection_keys, user_profile_key, changed_properties): # type: (list[db.Key], db.Key, list[unicode]) -> None from rogerthat.service.api import friends changed_properties = changed_properties or [] def trans(): models = db.get([user_profile_key] + friend_service_identity_connection_keys) # type: list user_profile = models.pop(0) # type: UserProfile assert isinstance(user_profile, UserProfile) friend_service_identity_connections = [] # type: list[FriendServiceIdentityConnection] for fsic in models: if not fsic: continue fsic.friend_name = user_profile.name fsic.friend_avatarId = user_profile.avatarId fsic.birthdate = user_profile.birthdate fsic.gender = user_profile.gender friend_service_identity_connections.append(fsic) if friend_service_identity_connections: db.put(friend_service_identity_connections) return user_profile, friend_service_identity_connections user_profile, fsics = db.run_in_transaction(trans) user_details = UserDetailsTO.fromUserProfile(user_profile) service_api_callbacks = [] service_users = {get_service_user_from_service_identity_user(fsic.service_identity_user) for fsic in fsics} for service_profile in get_service_profiles(list(service_users)): context = friends.update(friend_update_response_receiver, logServiceError, service_profile, user_details=user_details, changed_properties=changed_properties, DO_NOT_SAVE_RPCCALL_OBJECTS=True) if context: service_api_callbacks.append(context) logging.info('sending friend.update to %s/%s services', len(service_api_callbacks), len(service_users)) db.put(service_api_callbacks)
def start_flow(service_identity_user, message_parent_key, flow, members, check_friends, result_callback, tag=None, context=None, key=None, force_language=None, allow_reserved_tag=False, broadcast_type=None, broadcast_guid=None, flow_params=None): # key is in fact a force_message_flow_run_id svc_user = get_service_user_from_service_identity_user(service_identity_user) if isinstance(flow, (str, unicode)): mfd = get_message_flow_by_key_or_name(svc_user, flow) if not mfd or not mfd.user == svc_user: raise MessageFlowNotFoundException() if mfd.status != MessageFlowDesign.STATUS_VALID: raise MessageFlowNotValidException(mfd.validation_error) else: mfd = flow _validate_start_flow(service_identity_user, message_parent_key, members, check_friends, tag, allow_reserved_tag, flow_params) mfr = _create_message_flow_run(svc_user, service_identity_user, key, result_callback, tag, flow_params) message_flow_run_id = mfr.messageFlowRunId d = hashlib.sha256(message_flow_run_id) d.update('key for first message in flow!') try_or_defer(_execute_flow, service_identity_user, mfd, mfr, members, message_parent_key, context, d.hexdigest(), force_language=force_language, broadcast_type=broadcast_type, broadcast_guid=broadcast_guid, tag=tag, _transactional=db.is_in_transaction()) return message_flow_run_id
def _update_service_friends(friend_service_identity_connection_keys, user_profile_key): def trans(): user_profile = db.get(user_profile_key) friend_service_identity_connections = db.get(friend_service_identity_connection_keys) for fsic in friend_service_identity_connections: fsic.friend_name = user_profile.name fsic.friend_avatarId = user_profile.avatarId fsic.birthdate = user_profile.birthdate fsic.gender = user_profile.gender db.put(friend_service_identity_connections) return user_profile, friend_service_identity_connections user_profile, fsics = db.run_in_transaction(trans) from rogerthat.service.api import friends user_details = UserDetailsTO.fromUserProfile(user_profile) service_api_callbacks = list() service_users = set((get_service_user_from_service_identity_user(fsic.service_identity_user) for fsic in fsics)) for service_profile in get_service_profiles((u for u in service_users)): context = friends.update(friend_update_response_receiver, logServiceError, service_profile, user_details=user_details, DO_NOT_SAVE_RPCCALL_OBJECTS=True) if context: service_api_callbacks.append(context) logging.info('sending friend.update to %s/%s services', len(service_api_callbacks), len(service_users)) db.put(service_api_callbacks)
def get_all_archived_service_friend_keys_query(service_user): """Returns a query that results in all FriendServiceIdentityConnectionArchive of a service and all its identities. """ email = get_service_user_from_service_identity_user(service_user).email() + '/' return FriendServiceIdentityConnectionArchive.all(keys_only=True) \ .filter('service_identity_email >=', email) \ .filter('service_identity_email <', email + u"\ufffd")
def login_as(account): user = users.get_current_user() session_ = users.get_current_session() if not (user and session_): logging.warning("login_as called from unauthenticated context") return # Get service identities of session.user if session_.user.email() == account: session_ = switch_to_service_identity(session_, None, False, False) users.update_session_object(session_, session_.user) logging.info("Switching session of %s from %s to %s", session_.user, user, account) return session_.user.email() else: service_identity_user = users.User(account) logging.info("Validating if %s has a role in %s", session_.user, service_identity_user) if session_.has_access(account): service_profile = get_service_profile(get_service_user_from_service_identity_user(service_identity_user)) if service_profile.expiredAt > 0: raise ServiceExpiredException() session_ = switch_to_service_identity(session_, service_identity_user, False, False) service_user, _ = get_service_identity_tuple(service_identity_user) users.update_session_object(session_, service_user) logging.info("Switching session of %s from %s to %s", session_.user, user, service_identity_user) return service_identity_user.email() logging.critical("%s tried getting access to %s!", session_.user, account)
def newFlowMessage(request): app_user = users.get_current_user() sender = add_slash_default(users.User(request.message.sender)) message = request.message tag = sender_answer = step_id = None if MISSING not in (request.message_flow_run_id, request.step_id): step_id = request.step_id mfrr = get_message_flow_run_record(get_service_user_from_service_identity_user(sender), request.message_flow_run_id) if mfrr: tag = mfrr.tag is_mfr = False alert_flags = Message.ALERT_FLAG_SILENT flags = message.flags | Message.FLAG_LOCKED if message.message_type == Message.TYPE_FORM_MESSAGE: from rogerthat.bizz.messaging import sendForm message.member.member = create_app_user(users.User(message.member.member), get_app_id_from_app_user(app_user)).email() sendForm(sender, message.parent_key, app_user, message.message, message.form, flags, message.branding, tag, alert_flags, message.context, message.key, is_mfr, forced_member_status=message.member, forced_form_result=request.form_result, step_id=step_id, allow_reserved_tag=True) else: from rogerthat.bizz.messaging import sendMessage message.members[0].member = create_app_user(users.User(message.members[0].member), get_app_id_from_app_user(app_user)).email() sendMessage(sender, [UserMemberTO(app_user, alert_flags)], flags, message.timeout, message.parent_key, message.message, message.buttons, sender_answer, message.branding, tag, message.dismiss_button_ui_flags, message.context, message.key, is_mfr, forced_member_status=message.members[0], step_id=step_id, allow_reserved_tag=True)
def get_all_service_friend_keys_query(service_user): """Returns a query that results in all FriendServiceIdentityConnection of a service and all its identities.""" # service_user can be a service_identity_user email = get_service_user_from_service_identity_user(service_user).email() + '/' qry = db.GqlQuery( "SELECT __key__ FROM FriendServiceIdentityConnection WHERE service_identity_email >= :from_service_identity_email AND service_identity_email < :to_service_identity_email") qry.bind(from_service_identity_email=email, to_service_identity_email=email + u"\ufffd") return qry
def get_service_roles(email): service_identity_user = add_slash_default(users.User(email)) if not email.endswith('/') and is_service_identity_user(service_identity_user): service_user = get_service_user_from_service_identity_user(service_identity_user) return RolesReturnStatusTO.create(roles=map(RoleTO.fromServiceRole, list_service_roles(service_user)), service_identity_email=service_identity_user.email()) else: return RolesReturnStatusTO.create(success=False, errormsg=u"Service identity not found: %s" % service_identity_user.email())
def _run_update_friend_for_service_identity(service_identity_user, clear_broadcast_settings_cache, get_fsics_query_function, get_fsics_query_function_args, worker_queue=HIGH_LOAD_WORKER_QUEUE): service_user = get_service_user_from_service_identity_user(service_identity_user) should_clear = db.run_in_transaction(_should_clear_broadcast_settings_flag, service_user, clear_broadcast_settings_cache) _serialize_and_update_friend_for_service_identity(service_identity_user, should_clear, get_fsics_query_function, get_fsics_query_function_args, worker_queue)
def _match_roles_of_item(app_user, news_item): if not news_item.has_roles(): return True service_user = get_service_user_from_service_identity_user(news_item.sender) role_ids = news_item.role_ids roles = [role for role in get_service_roles_by_ids(service_user, role_ids) if role is not None] user_profile = get_user_profile(app_user) service_identity = get_service_identity(news_item.sender) return any([has_role(service_identity, user_profile, role) for role in roles])
def update_beacons(service_identity_user, beacons): from rogerthat.bizz.service import BeaconAlreadyCoupledException, NoBeaconRegionFoundException if beacons is MISSING or beacons is None: beacons = list() service_user = get_service_user_from_service_identity_user(service_identity_user) identifier = get_identity_from_service_identity_user(service_identity_user) @db.non_transactional def _validate_beacon(beacon_name, beacon_uuid, beacon_major, beacon_minor, supported_app_ids): b = get_beacon(beacon_uuid, beacon_name) if b and b.service_identity_user != service_identity_user: raise BeaconAlreadyCoupledException(beacon_uuid, beacon_major, beacon_minor) for beacon_region in BeaconRegion.all().filter('uuid', beacon_uuid): if beacon_region.major is not None: if beacon_region.major != beacon_major: continue # the beacon does not belong to this region if beacon_region.minor is not None: if beacon_region.mino != beacon_minor: continue # the beacon does not belong to this region if beacon_region.app_id not in supported_app_ids: continue # the service_identity does not support this app break else: raise NoBeaconRegionFoundException(beacon_uuid, beacon_major, beacon_minor) def trans(): l = get_beacons(service_user, identifier) db.delete(l) beacons_to_put = list() for beacon in beacons: beacon_name = u"%s|%s" % (beacon.major, beacon.minor) beacon_uuid = beacon.uuid.lower() _validate_beacon(beacon_name, beacon_uuid, beacon.major, beacon.minor, get_service_identity(service_identity_user).appIds) b = Beacon(key=Beacon.create_key(service_identity_user, beacon_name)) b.uuid = beacon_uuid b.name = beacon_name b.tag = beacon.tag b.service_identity = identifier b.creation_time = now() beacons_to_put.append(b) if beacons_to_put: db.put(beacons_to_put) if db.is_in_transaction(): return trans() else: return db.run_in_transaction(trans)
def store_stats_qr_scans(counters): sid_rpcs = list() for (service_identity_email, sid), sid_counters in counters.iteritems(): sid_key = db.Key.from_path(ServiceInteractionDef.kind(), sid, parent=parent_key(get_service_user_from_service_identity_user(users.User(service_identity_email)))) sid_rpcs.append((db.get_async(sid_key), sid_counters)) for sid_rpc, sid_counters in sid_rpcs: sid = sid_rpc.get_result() sid.totalScanCount += sid_counters["total"] sid.scannedFromRogerthatCount += sid_counters["from_rogerthat"] sid.scannedFromOutsideRogerthatOnSupportedPlatformCount += sid_counters['supported'] sid.scannedFromOutsideRogerthatOnUnsupportedPlatformCount += sid_counters['unsupported'] put_rpcs['qr_scans'].append(db.put_async(sid))
def trans(): app_user = users.User(user_profile.key().name()) if user_profile.isCreatedForService: logging.debug('%s is created for service(s) %s', app_user, user_profile.owningServiceEmails) return service_user = get_service_user_from_service_identity_user(service_identity_user) fsic_key = FriendServiceIdentityConnection.createKey(app_user, service_identity_user) friend_map_key = get_friends_map_key_by_user(app_user) fsic, friend_map, si, service_profile = \ db.get([fsic_key, friend_map_key, ServiceIdentity.keyFromUser(service_identity_user), get_profile_key(service_user)]) azzert(si and service_profile) if fsic and not fsic.deleted: # they are friends alert_flags = Message.ALERT_FLAG_VIBRATE answers = [] step_id = u'Connected' elif friend_map: # Fake a deleted connection between service and human user to be able to show the service's avatar on the phone fake_friend_connection(friend_map_key, si) alert_flags = Message.ALERT_FLAG_SILENT answers = create_add_to_services_button(service_profile.defaultLanguage) step_id = u'Not connected' else: logging.warn(u'No FSIC nor FriendMap found for %s', app_user) return member = UserMemberTO(app_user, alert_flags) flags = Message.FLAG_ALLOW_DISMISS | Message.FLAG_AUTO_LOCK timeout = 0 parent_key = None sender_answer = None branding = si.descriptionBranding if is_test: step_id = None m = sendMessage(service_identity_user, [member], flags, timeout, parent_key, message, answers, sender_answer, branding, tag, check_friends=False, allow_reserved_tag=True, step_id=step_id) m.invitor = service_identity_user m.invitee = app_user m.origin = ORIGIN_SERVICE_INVITE m.servicetag = APP_BROADCAST_TAG m.put()
def handle_service_tracker_results(app_user, service_identity_user, location): slt = get_current_tracker(app_user, service_identity_user) if not slt: logging.info("Not sending location as the tracker has timed out or was disabled.") return if not slt.notified: # Calculate timezone based on users location deferred.defer(notify_location_tracking_enabled, location, service_identity_user, app_user, slt.key()) user_details = [UserDetailsTO.fromUserProfile(get_user_profile(app_user))] service_profile = get_service_profile(get_service_user_from_service_identity_user(service_identity_user)) location_fix(location_fix_response_receiver, logServiceError, service_profile, service_identity=get_identity_from_service_identity_user(service_identity_user), user_details=user_details, location=location, tracker_key=slt.encrypted_key())
def schedule_update_a_friend_of_a_service_identity_user(service_identity_user, target_user, force=False, clear_broadcast_settings_cache=False): '''Schedule update of 1 service_identity to 1 user''' azzert('/' in service_identity_user.email(), "Expecting a service identity user.") service_user = get_service_user_from_service_identity_user(service_identity_user) if db.is_in_transaction(): service_profile_or_service_user = get_service_profile(service_user, False) else: service_profile_or_service_user = service_user if not force and not _must_continue_with_update_service(service_profile_or_service_user, False, clear_broadcast_settings_cache): return deferred.defer(_run_update_friends_for_service_user, service_user, force, False, clear_broadcast_settings_cache, get_one_friend_service_identity_connection_keys_query, [service_identity_user, target_user], _transactional=db.is_in_transaction())
def post(self): app_id = self.request.POST.get("app_id", None) self.response.headers['Content-Type'] = 'text/json' if app_id: app = get_app_by_id(app_id) if app: app_dict = serialize_complex_value(AppTO.fromModel(app, True), AppTO, False) # append service_role_names to app_dict for acs in app_dict['auto_connected_services']: service_user = get_service_user_from_service_identity_user(users.User(acs['service_identity_email'])) acs['service_role_names'] = [r.name for r in get_service_roles_by_ids(service_user, acs['service_roles'])] logging.debug("Returning %s", app_dict) self.response.out.write(json.dumps(dict(success=True, errormsg=None, app=app_dict))) return self.response.out.write(json.dumps(dict(success=False, errormsg=u"Could not find app")))
def get_group_info(service_identity_user, broadcast_type=None, app_ids=None, news_item=None, has_locations=False): check_broadcast_type = None check_app_ids = [] if news_item: check_broadcast_type = broadcast_type if broadcast_type else news_item.broadcast_type check_app_ids = news_item.app_ids if app_ids: for app_id in app_ids: if app_id not in check_app_ids: check_app_ids.append(app_id) else: if broadcast_type: check_broadcast_type = broadcast_type if app_ids: check_app_ids = app_ids logging.debug('debugging_news get_group_info check_broadcast_type:%s check_app_ids:%s', check_broadcast_type, check_app_ids) if not check_broadcast_type or not check_app_ids: return [], [] service_user = get_service_user_from_service_identity_user(service_identity_user) group_types = get_group_types_for_service(service_user, check_broadcast_type) logging.debug('debugging_news get_group_info group_types:%s', group_types) if not group_types: return [], [] if has_locations: group_types.append(NewsGroup.TYPE_LOCATION) si = get_service_identity(service_identity_user) group_ids = [] for group_type in group_types: if group_type in (NewsGroup.TYPE_PROMOTIONS, NewsGroup.TYPE_PRESS): app_ids = [] for app_id in check_app_ids: ns = NewsStream.create_key(app_id).get() if ns and not ns.should_create_groups: app_ids.append(app_id) else: app_ids = [si.app_id] group_ids.extend(get_group_ids_for_type(group_type, si.app_id, app_ids)) logging.debug('debugging_news get_group_info group_ids:%s', group_ids) return group_types, group_ids
def trans(): app = db.get(app_key) identities = list() for acs in app.auto_connected_services: if get_service_user_from_service_identity_user(users.User(acs.service_identity_email)).email() == service_user.email(): identities.append(acs.service_identity_email) updated = False if identities: updated = True for service_identity_email in identities: app.auto_connected_services.remove(service_identity_email) if service_user.email() in app.admin_services: updated = True app.admin_services.remove(service_user.email()) if updated: app.put()
def _validate_job(from_service_user, to_service_user): # FROM != TO bizz_check(from_service_user.email() != to_service_user.email(), 'FROM and TO should not be equal') # FROM should exist and be a ServiceProfile from_service_profile = _get_profile_not_cached(from_service_user) bizz_check(from_service_profile, 'ServiceProfile %s not found' % from_service_user) bizz_check(isinstance(from_service_profile, ServiceProfile), 'Profile %s is not of expected type ServiceProfile, but of type %s' % (from_service_user, from_service_profile.kind())) # TO should not exist to_profile = _get_profile_not_cached(to_service_user) if to_profile: raise BusinessException('%s %s already exists' % (to_profile.kind(), to_service_user)) # FROM should not be an auto_connected_service in an App for app in App.all(): if from_service_user.email() in app.admin_services: raise BusinessException('FROM should not be an app admin service (found in app %s)' % app.app_id) for acs in app.auto_connected_services: acs_si_user = users.User(acs.service_identity_email) if get_service_user_from_service_identity_user(acs_si_user).email() == from_service_user.email(): raise BusinessException('FROM should not be an AutoConnectedService (found %s in app %s)' % (acs_si_user, app.app_id)) # Validate that there are no running jobs for <from_service> or <to_service> def get_base_query(): return MigrateServiceJob.all().filter('phase !=', MigrateServiceJob.PHASE_DONE) for service_user in (from_service_user, to_service_user): for prop in ('from_service_user', 'to_service_user'): job = get_base_query().filter(prop, service_user).get() if job: raise BusinessException('There already is a MigrateServiceJob with %s=%s\n%s' % (prop, service_user, db.to_dict(job))) return from_service_profile
def fromProfileInfo(profile_info): from rogerthat.bizz.friends import userCode from rogerthat.dal.profile import get_service_profile from rogerthat.utils.service import get_service_user_from_service_identity_user p = CompleteProfileTO() p.isService = profile_info.isServiceIdentity p.name = profile_info.name if p.isService: p.userCode = None p.allLanguages = [] p.allLanguagesStr = [] p.userLanguage = None profile = get_service_profile(get_service_user_from_service_identity_user(profile_info.user)) p.organizationType = profile.organizationType else: p.userCode = userCode(profile_info.user) p.allLanguages = get_officially_supported_languages(iso_format=False) p.allLanguagesStr = map(get_full_language_string, p.allLanguages) p.userLanguage = profile_info.language p.organizationType = 0 return p
def _populateTO(message, msgTO, member=None): msgTO.key = message.mkey pk = message.parent_key() if pk: msgTO.parent_key = pk.name() else: msgTO.parent_key = None msgTO.sender = remove_app_id(remove_slash_default(message.sender, warn=True)).email() msgTO.flags = message.flags msgTO.timestamp = message.creationTimestamp msgTO.threadTimestamp = message.timestamp msgTO.message = u"" if message.message is None else message.message branding = message.branding if branding: from rogerthat.bizz.branding import OLD_SYSTEM_BRANDING_HASHES if branding in OLD_SYSTEM_BRANDING_HASHES: branding = get_app_by_id(App.APP_ID_ROGERTHAT).core_branding_hash else: branding = unicode(branding) msgTO.branding = branding msgTO.alert_flags = message.alert_flags if message.alert_flags is not None else Message.ALERT_FLAG_VIBRATE msgTO.message_type = message.TYPE if member and message.broadcast_type: from rogerthat.bizz.i18n import get_translator from rogerthat.dal.profile import get_user_profile lang = get_user_profile(member).language translator = get_translator(get_service_user_from_service_identity_user(message.sender), [ServiceTranslation.BROADCAST_TYPE], lang) msgTO.broadcast_type = translator.translate(ServiceTranslation.BROADCAST_TYPE, message.broadcast_type, lang) else: msgTO.broadcast_type = None msgTO.attachments = map(AttachmentTO.fromModel, sorted(message.attachments or [], key=lambda a: a.index)) msgTO.thread_avatar_hash = message.thread_avatar_hash msgTO.thread_background_color = message.thread_background_color msgTO.thread_text_color = message.thread_text_color msgTO.priority = Message.PRIORITY_NORMAL if message.priority is None else message.priority msgTO.default_priority = Message.PRIORITY_NORMAL if message.default_priority is None else message.default_priority msgTO.default_sticky = False if message.default_sticky is None else message.default_sticky return msgTO
def ack_test_broadcast(message): test_person = message.broadcast_test_person logging.info(u"%s answered broadcast flow" % test_person.email()) btn_index = message.memberStatusses[message.members.index(test_person)].button_index if btn_index == message.buttons[BROADCAST_RETRY_ID].index: flow = Broadcast.get(message.broadcast_key).message_flow start_flow(add_slash_default(message.sender), message_parent_key=message.pkey, flow=flow, members=[test_person], check_friends=False, result_callback=False, tag=json.dumps({Broadcast.TAG_MC_BROADCAST: message.broadcast_key}), broadcast_type=message.broadcast_type) else: accepted = btn_index == message.buttons[BROADCAST_ACCEPT_ID].index def txn_update_tester_status(): broadcast = Broadcast.get(message.broadcast_key) if broadcast: status = Broadcast.TEST_PERSON_STATUS_ACCEPTED if accepted else Broadcast.TEST_PERSON_STATUS_DECLINED broadcast.set_status(test_person, status) broadcast.put() return bool(broadcast) if db.run_in_transaction(txn_update_tester_status): channel.send_message(get_service_user_from_service_identity_user(message.sender), u'rogerthat.broadcast.changes', broadcast_key=message.broadcast_key)
def _setup_notification_settings_for_user(app_user, service_identity_user, group_types): logging.debug('_setup_notification_settings_for_user siu: %s', service_identity_user) logging.debug('_setup_notification_settings_for_user group_types: %s', group_types) service_user = get_service_user_from_service_identity_user(service_identity_user) nss = NewsSettingsService.create_key(service_user).get() if not nss: return [] notifications_enabled_for_group_ids = [] for group_type, group_ids in group_types.iteritems(): g = nss.get_group(group_type) if not g: continue notifications_enabled_for_group_ids.extend(group_ids) logging.debug('_setup_notification_settings_for_user notifications_enabled_for_group_ids: %s', notifications_enabled_for_group_ids) if not notifications_enabled_for_group_ids: return [] to_put = [] for group_id in notifications_enabled_for_group_ids: nsus_key = NewsSettingsUserService.create_key(app_user, group_id, service_identity_user) nsus = nsus_key.get() if not nsus: nsus = NewsSettingsUserService(key=nsus_key, group_id=group_id, notifications=NewsNotificationStatus.NOT_SET, blocked=False) if nsus.notifications != NewsNotificationStatus.NOT_SET: continue nsus.notifications = NewsNotificationStatus.ENABLED to_put.append(nsus) return to_put
def _populate_items(self, service_identity_user, translator, language, staticFlowBrandings, target_user_profile, existence): has_role_cache = dict() service_user = get_service_user_from_service_identity_user(service_identity_user) def is_item_visible(smd): if not smd.roles: return True if not target_user_profile: return False from rogerthat.bizz.roles import has_role for role_id in sorted(smd.roles): user_has_role = has_role_cache.get(role_id) if user_has_role is None: role = get_service_role_by_id(service_user, role_id) user_has_role = has_role_cache[role_id] = has_role(service_identity_user, target_user_profile, role) if user_has_role: return True return False self.items = [ServiceMenuItemTO.fromServiceMenuDef(smd, translator, language, staticFlowBrandings, target_user_profile, service_identity_user, existence) for smd in filter(is_item_visible, get_service_menu_items(service_identity_user))]
def get_service_menu_item_by_coordinates(service_identity_user, coords): service_user = get_service_user_from_service_identity_user(service_identity_user) return ServiceMenuDef.get_by_key_name("x".join((str(x) for x in coords)), parent=parent_key(service_user))
def get_service_menu_items(service_identity_user): svc_user = get_service_user_from_service_identity_user(service_identity_user) qry = ServiceMenuDef.gql("WHERE ANCESTOR IS :ancestor") qry.bind(ancestor=parent_key(svc_user)) return generator(qry.run())
def _service_identity_worker(si_key): si = db.get(si_key) service_user = get_service_user_from_service_identity_user( si.service_identity_user) if not is_trial_service(service_user): re_index(si.service_identity_user)
def service_user(self): return get_service_user_from_service_identity_user( self.service_identity_user)
def put_news_item(service_identity_user, title, message, broadcast_type, sponsored, image, action_button, order_items, news_type, qr_code_caption, app_ids, scheduled_at, news_id=None, broadcast_on_facebook=False, broadcast_on_twitter=False, facebook_access_token=None, target_audience=None, role_ids=None, host=None): """ Creates a news item first then processes the payment if necessary (not necessary for non-promoted posts). If the payment was unsuccessful it will be retried in a deferred task. Args: service_identity_user (users.User) title (unicode) message (unicode) broadcast_type (unicode) sponsored (bool) image (unicode) action_button (NewsActionButtonTO) order_items (list of OrderItemTO) news_type (int) qr_code_caption (unicode) app_ids (list of unicode) scheduled_at (long) news_id (long): id of the news item to update. When not provided a new news item will be created. broadcast_on_facebook (bool) broadcast_on_twitter (bool) facebook_access_token (unicode): user or page access token target_audience (NewsTargetAudienceTO) role_ids (list of long) the list of role ids to filter sending the news to their members host (unicode): host of the api request (used for social media apps) Returns: news_item (NewsBroadcastItemTO) """ if not order_items or order_items is MISSING: order_items = [] if news_type == NewsItem.TYPE_QR_CODE: sln_settings = get_solution_settings( get_service_user_from_service_identity_user(service_identity_user)) azzert(SolutionModule.LOYALTY in sln_settings.modules) sponsored_until = None should_save_coupon = news_type == NewsItem.TYPE_QR_CODE and not news_id sponsored_app_ids = set() extra_app_ids = [] si = get_service_identity(service_identity_user) for order_item in reversed(order_items): if order_item.product == Product.PRODUCT_NEWS_PROMOTION and sponsored: azzert(order_item.app_id) azzert(order_item.app_id not in sponsored_app_ids) sponsored_app_ids.add(order_item.app_id) order_item.count = get_sponsored_news_count_in_app( service_identity_user, order_item.app_id).count elif order_item.product == Product.PRODUCT_EXTRA_CITY: azzert(order_item.app_id) azzert(order_item.app_id not in extra_app_ids) extra_app_ids.append(order_item.app_id) if order_item.app_id in si.appIds: order_items.remove(order_item) else: raise BusinessException('Invalid product %s' % order_item.product) if not news_id and not app_ids: raise BusinessException( 'Please select at least one app to publish this news in') if sponsored: sponsored_until_date = datetime.datetime.utcnow() + datetime.timedelta( days=SPONSOR_DAYS) sponsored_until = long(sponsored_until_date.strftime('%s')) # for sponsored news that is free in certain apps no order item is given, so add it here sponsored_counts = get_sponsored_news_count(service_identity_user, app_ids) for sponsored_count in sponsored_counts: if sponsored_count.remaining_free != 0 and sponsored_count.app_id in app_ids: sponsored_app_ids.add(sponsored_count.app_id) app_ids = list(sponsored_app_ids) service_user, identity = get_service_identity_tuple(service_identity_user) default_app = get_app(si.defaultAppId) if App.APP_ID_ROGERTHAT in si.appIds and App.APP_ID_ROGERTHAT not in app_ids: app_ids.append(App.APP_ID_ROGERTHAT) if default_app.demo and App.APP_ID_ROGERTHAT in app_ids: app_ids.remove(App.APP_ID_ROGERTHAT) kwargs = { 'sticky': sponsored, 'sticky_until': sponsored_until, 'message': message, 'broadcast_type': broadcast_type, 'service_identity': identity, 'news_id': news_id, 'app_ids': app_ids, 'image': image, 'scheduled_at': scheduled_at, 'target_audience': target_audience, 'role_ids': role_ids } if not news_id: kwargs['news_type'] = news_type if news_type == NewsItem.TYPE_QR_CODE: if should_save_coupon: def trans(): coupon = NewsCoupon( parent=NewsCoupon.create_parent_key(service_identity_user), content=qr_code_caption) coupon.put() return coupon coupon = db.run_in_transaction(trans) kwargs['qr_code_content'] = u'%s' % json.dumps({'c': coupon.id}) kwargs['qr_code_caption'] = qr_code_caption elif news_type == NewsItem.TYPE_NORMAL: kwargs.update({ 'action_buttons': [action_button] if action_button else [], 'title': title }) else: raise BusinessException('Invalid news type') for key, value in kwargs.items(): if value is MISSING: del kwargs[key] with users.set_user(service_user): try: def trans(): news_item = news.publish(accept_missing=True, **kwargs) if should_save_coupon: _save_coupon_news_id(news_item.id, coupon) elif news_type == NewsItem.TYPE_QR_CODE and qr_code_caption is not MISSING and qr_code_caption and news_id: news_coupon = NewsCoupon.get_by_news_id( service_identity_user, news_id) if news_coupon: news_coupon.content = qr_code_caption news_coupon.put() else: logging.warn( 'Not updating qr_code_caption for non-existing coupon for news with id %d', news_id) if order_items: create_and_pay_news_order(service_user, news_item.id, order_items) return news_item news_item = run_in_xg_transaction(trans) if broadcast_on_facebook or broadcast_on_twitter: if scheduled_at is not MISSING and scheduled_at > 0: schedule_post_to_social_media(service_user, host, broadcast_on_facebook, broadcast_on_twitter, facebook_access_token, news_item.id, scheduled_at) else: post_to_social_media(service_user, broadcast_on_facebook, broadcast_on_twitter, facebook_access_token, news_item.id) return NewsBroadcastItemTO.from_news_item_to( news_item, broadcast_on_facebook, broadcast_on_twitter) except: if should_save_coupon: db.delete_async(coupon) raise
def finish_registration(mobile_account, mobileInfo, accounts, invitor_code, invitor_secret, ipaddress): from rogerthat.service.api import friends as service_api_friends m = get_mobile_by_account(mobile_account) mobile_key = m.key() ms_key = MobileSettings.get(m).key() profile_key = get_user_profile_key(m.user) def trans(): mobile, ms, my_profile = db.get((mobile_key, ms_key, profile_key)) mobile.status = mobile.status | Mobile.STATUS_REGISTERED mobile.type = mobileInfo.app_type mobile.simCountry = mobileInfo.sim_country if mobileInfo.sim_country != MISSING else None mobile.simCountryCode = mobileInfo.sim_country_code if mobileInfo.sim_country_code != MISSING else None mobile.simCarrierCode = mobileInfo.sim_carrier_code if mobileInfo.sim_carrier_code != MISSING else None mobile.simCarrierName = mobileInfo.sim_carrier_name if mobileInfo.sim_carrier_name != MISSING else None mobile.netCountry = mobileInfo.net_country if mobileInfo.net_country != MISSING else None mobile.netCountryCode = mobileInfo.net_country_code if mobileInfo.net_country_code != MISSING else None mobile.netCarrierCode = mobileInfo.net_carrier_code if mobileInfo.net_carrier_code != MISSING else None mobile.netCarrierName = mobileInfo.net_carrier_name if mobileInfo.net_carrier_name != MISSING else None mobile.hardwareModel = mobileInfo.device_model_name mobile.osVersion = mobileInfo.device_os_version if mobileInfo.device_os_version != MISSING else None mobile.localeLanguage = mobileInfo.locale_language if mobileInfo.locale_language and mobileInfo.locale_language != MISSING else DEFAULT_LANGUAGE mobile.localeCountry = mobileInfo.locale_country mobile.timezone = mobileInfo.timezone if mobileInfo.timezone != MISSING else None mobile.timezoneDeltaGMT = mobileInfo.timezone_delta_gmt if mobileInfo.timezone_delta_gmt != MISSING else None if mobileInfo.app_major_version != MISSING and mobileInfo.app_minor_version != MISSING: ms.majorVersion = mobileInfo.app_major_version ms.minorVersion = mobileInfo.app_minor_version # This is the official place where we set the profile language my_profile.language = mobile.localeLanguage my_profile.country = mobile.netCountry or mobile.simCountry or mobile.localeCountry my_profile.timezone = mobile.timezone my_profile.timezoneDeltaGMT = mobile.timezoneDeltaGMT my_profile.mobiles = MobileDetails() my_profile.mobiles.addNew(mobile.account, mobile.type, mobile.pushId, mobile.app_id) mobile.put() ms.put() my_profile.put() deferred.defer(_finishup_mobile_registration, mobile, accounts, invitor_code, invitor_secret, ipaddress, ms_key, _transactional=True) return mobile, my_profile xg_on = db.create_transaction_options(xg=True) mobile, my_profile = db.run_in_transaction_options(xg_on, trans) channel.send_message(mobile.user, u'com.mobicage.registration.finished') typestr = "Unknown type" try: typestr = Mobile.typeAsString(mobile.type) except ValueError: pass server_settings = get_server_settings() registration = get_registration_by_mobile(mobile) if registration: InstallationLog(parent=registration.installation, timestamp=now(), registration=registration, mobile=mobile, profile=my_profile, description="Registration successful.").put() if registration.installation and registration.installation.qr_url: service_user = get_service_user_from_service_identity_user(registration.installation.service_identity_user) service_identity = get_identity_from_service_identity_user(registration.installation.service_identity_user) svc_profile = get_service_profile(service_user) user_details = [UserDetailsTO.fromUserProfile(my_profile)] if registration.installation.service_callback_result == ACCEPT_AND_CONNECT_ID: service_identity_user = create_service_identity_user(service_user, service_identity) si = get_service_identity(service_identity_user) bizz_check(si, "ServiceIdentity %s not found" % service_identity_user) xmpp.send_message(server_settings.xmppInfoMembers, "User %s registered %s (%s) with account:\n%s\nFor service %s %s" % ( mobile.user, mobile.hardwareModel, typestr, mobile.account, si.name, service_identity_user), message_type=xmpp.MESSAGE_TYPE_CHAT) app_id = get_app_id_from_app_user(mobile.user) if app_id not in si.appIds: si.appIds.append(app_id) put_and_invalidate_cache(si) try_or_defer(makeFriends, mobile.user, service_identity_user, original_invitee=None, servicetag=None, origin=None, notify_invitee=False, notify_invitor=False, user_data=None) else: xmpp.send_message(server_settings.xmppInfoMembers, "User %s registered %s (%s) with account:\n%s" % ( mobile.user, mobile.hardwareModel, typestr, mobile.account), message_type=xmpp.MESSAGE_TYPE_CHAT) service_api_friends.register_result(register_result_response_receiver, logServiceError, svc_profile, service_identity=service_identity, user_details=user_details, origin=REGISTRATION_ORIGIN_QR) else: xmpp.send_message(server_settings.xmppInfoMembers, "User %s registered %s (%s) with account:\n%s" % ( mobile.user, mobile.hardwareModel, typestr, mobile.account), message_type=xmpp.MESSAGE_TYPE_CHAT) app = get_app_by_id(get_app_id_from_app_user(mobile.user)) if app.admin_services: service_profiles = filter(None, db.get((get_profile_key(users.User(e)) for e in app.admin_services))) if service_profiles: user_details = [UserDetailsTO.fromUserProfile(my_profile)] for service_profile in service_profiles: service_api_friends.register_result(register_result_response_receiver, logServiceError, service_profile, service_identity=ServiceIdentity.DEFAULT, user_details=user_details, origin=REGISTRATION_ORIGIN_DEFAULT) else: xmpp.send_message(server_settings.xmppInfoMembers, "User %s registered %s (%s) with account:\n%s\nBut registration model was not found!" % ( mobile.user, mobile.hardwareModel, typestr, mobile.account), message_type=xmpp.MESSAGE_TYPE_CHAT) return mobile
def _create_message_flow_run_xml_doc(service_identity_user, message_flow_design, message_flow_run_record, members, force_language): service_user = get_service_user_from_service_identity_user(service_identity_user) if not message_flow_design.xml: # Must regenerate xml subflowdict = get_message_flow_design_context(message_flow_design) translator = get_translator(service_user, ServiceTranslation.MFLOW_TYPES) definition_doc = parseString(message_flow_design_to_xml( service_user, message_flow_design, translator, subflowdict)[0].encode('utf-8')) message_flow_design.xml = definition_doc.toxml('utf-8') message_flow_design.put() logging.warning("Message flow design with empty xml property discovered!!!\nkey = %s" % message_flow_design.key()) else: definition_doc = parseString(message_flow_design.xml.encode('utf-8')) run = MessageFlowRunSub(launchTimestamp=message_flow_run_record.creationtime) si = get_service_identity(service_identity_user) run.set_serviceName(si.name) run.set_serviceDisplayEmail(si.qualifiedIdentifier or si.user.email()) run.set_serviceEmail(si.user.email()) run.set_flowParams(message_flow_run_record.flow_params) if si.serviceData: run.set_serviceData(json.dumps(si.serviceData.to_json_dict())) else: run.set_serviceData(si.appData) fallback_language = force_language or get_service_profile(service_user).defaultLanguage mf_languages = list() if definition_doc.documentElement.localName == 'messageFlowDefinitionSet': for definition_element in definition_doc.documentElement.childNodes: if definition_element.localName == 'definition': mf_languages.append(definition_element.getAttribute('language')) elif definition_doc.documentElement.localName == 'definition': mf_languages.append(fallback_language) else: azzert(False, "Unexpected tag name: %s" % definition_doc.documentElement.localName) # if force_language supplied, check if it's in mf_languages if force_language: bizz_check(force_language in mf_languages, "Can not run in %s." % get_full_language_string(force_language)) userprofiles = get_profile_infos(members, expected_types=[UserProfile] * len(members)) user_datas = db.get([UserData.createKey(member, service_identity_user) for member in members]) for i, p in enumerate(userprofiles): member_run_language = force_language or (p.language if p.language in mf_languages else fallback_language) human_user, app_id = get_app_user_tuple(p.user) if user_datas[i]: if user_datas[i].userData: user_data = json.dumps(user_datas[i].userData.to_json_dict()) else: user_data = user_datas[i].data else: user_data = None run.add_memberRun(MemberRunSub(status="SUBMITTED", email=human_user.email(), name=p.name, language=member_run_language, appId=app_id, avatarUrl=p.avatarUrl, userData=user_data)) xml = StringIO() xml.write("""<?xml version="1.0" encoding="utf-8"?>\n""") run.export(xml, 0, namespaceprefix_='', namespacedef_='xmlns="https://rogerth.at/api/1/MessageFlow.xsd"', name_='messageFlowRun') xml.reset() xml_doc = parse(xml) for member_run_child_node in xml_doc.documentElement.childNodes: if member_run_child_node.localName == "memberRun": break else: azzert(False, "No child nodes of type 'memberRun' found for xml:\n%s" % xml) # put memberRun in xml if definition_doc.documentElement.localName == 'messageFlowDefinitionSet': for definition_element in definition_doc.documentElement.childNodes: if definition_element.localName == 'definition': xml_doc.documentElement.insertBefore(definition_element, member_run_child_node) elif definition_doc.documentElement.localName == 'definition': xml_doc.documentElement.insertBefore(definition_doc.documentElement, member_run_child_node) else: azzert(False, "Unexpected tag name: %s" % definition_doc.documentElement.localName) return xml_doc
def start_local_flow(service_identity_user, thread_key, xml, members, tag=None, context=None, force_language=None, download_attachments_upfront=False, push_message=None, parent_message_key=None, flow=None, flow_params=None, check_friends=True): _validate_start_flow(service_identity_user, thread_key, members, tag=tag, check_friends=check_friends) service_user = get_service_user_from_service_identity_user(service_identity_user) if flow: if xml: raise InvalidValueException('xml', 'parameter "xml" cannot be set when property "flow" is set') mfd = get_message_flow_by_key_or_name(service_user, flow) if not mfd or not mfd.user == service_user: raise MessageFlowNotFoundException() if mfd.status != MessageFlowDesign.STATUS_VALID: raise MessageFlowNotValidException(mfd.validation_error) xml = mfd.xml js_flow_dict = generate_js_flow_cached(service_user, xml, context, minify=False, parent_message_key=parent_message_key, must_validate=True) # js_flow_dict = { language : (<compiled JS flow>, brandings, attachments) } if force_language and force_language is not MISSING: if force_language not in js_flow_dict: raise InvalidMessageFlowLanguageException(json.dumps(js_flow_dict.keys()), force_language) forced_flow = js_flow_dict[force_language] else: forced_flow = None extra_user = [] if service_user == MC_DASHBOARD else [service_identity_user] profile_infos = {profile_info.user: profile_info for profile_info in get_profile_infos(members + extra_user)} mfr = _create_message_flow_run(service_user, service_identity_user, result_callback=False, tag=tag) message_flow_run_id = mfr.messageFlowRunId for app_user in members: if forced_flow: flow_definition, brandings, attachments = forced_flow else: target_language = profile_infos[app_user].language if target_language not in js_flow_dict: # fall back to service default language target_language = get_service_profile(service_user).defaultLanguage if target_language not in js_flow_dict: if len(js_flow_dict) == 1: target_language = js_flow_dict.keys()[0] else: raise InvalidMessageFlowLanguageException(json.dumps(js_flow_dict.keys()), target_language) flow_definition, brandings, attachments = js_flow_dict[target_language] force_skip_attachments_download = False mobiles = profile_infos[app_user].mobiles if push_message: for mobile_detail in mobiles: if mobile_detail.type_ == Mobile.TYPE_IPHONE_HTTP_APNS_KICK and mobile_detail.pushId: force_skip_attachments_download = True break request = StartFlowRequestTO() request.attachments_to_dwnl = attachments if download_attachments_upfront and not force_skip_attachments_download else list() request.brandings_to_dwnl = brandings request.service = remove_slash_default(service_identity_user).email() request.static_flow = compress_js_flow_definition(flow_definition) request.static_flow_hash = unicode(md5_hex(flow_definition)) request.parent_message_key = thread_key request.message_flow_run_id = message_flow_run_id request.flow_params = flow_params if service_user == MC_DASHBOARD: sender_name = get_app_by_id(get_app_id_from_app_user(app_user)).name else: sender_name = profile_infos[service_identity_user].name kwargs = { CAPI_KEYWORD_PUSH_DATA: StartLocalFlowNotification(sender_name, push_message) } startFlow(start_flow_response_handler, logError, app_user, request=request, **kwargs) if push_message: send_apple_push_message(push_message, sender_name, mobiles) return message_flow_run_id
def get(self): user = users.get_current_user() if not user: signin_path = self.get_custom_signin_path(self.get_request_host()) if signin_path and self.request.path != signin_path: return self.redirect(signin_path) session_ = None user_services = None owning_user_services = None should_show_service_picker = False session_user = None session_service_identity_user = None loading_enabled = False if user: session_ = users.get_current_session() # Support reloading user_account = self.request.get("user") if user_account and user_account != user.email(): if not login_as(user_account): self.response.write("<html><body>You don't have access to account %s. This problem is logged and may cause legal action against you.</body></html>" % user_account) return user = users.get_current_user() session_ = users.get_current_session() mobile_count = get_user_active_mobiles_count(user) my_profile_info = get_profile_info(user, skip_warning=True) if not my_profile_info: my_profile_info = create_user_profile(user, user.email()) myavatarid = my_profile_info.avatarId if my_profile_info.isServiceIdentity: myname = my_profile_info.name or my_profile_info.qualifiedIdentifier or user.email() else: myname = my_profile_info.name or user.email() if my_profile_info.owningServiceEmails and my_profile_info.isCreatedForService: should_show_service_picker = True my_owning_service_identity_users = [create_service_identity_user(users.User(owning_service_email)) for owning_service_email in my_profile_info.owningServiceEmails] my_owning_service_identities = get_service_identities_by_service_identity_users(my_owning_service_identity_users) result = list() for si in my_owning_service_identities: result.append(dict(is_default=si.is_default, service_user=si.service_user.email(), service_identity_user=si.service_identity_user.email(), name=si.name, description=si.description, avatar_url=si.avatarUrl)) owning_user_services = result myname = myname.replace("\\", "\\\\").replace("'", "\\'") is_service = my_profile_info.isServiceIdentity is_trial_service_ = is_trial_service(get_service_user_from_service_identity_user(user)) if is_service else False loading_enabled = not is_service user_services = session_.service_users session_user = session_.user session_service_identity_user = session_.service_identity_user else: mobile_count = 0 my_profile_info = None myavatarid = None myname = None is_service = False is_trial_service_ = False user_services = None owning_user_services = None template_params = { 'appscale': APPSCALE, 'continue': "/", 'debug': DEBUG, 'user': user, 'myavatarid': myavatarid, 'myname': myname, 'mobile_count': mobile_count, 'is_service': is_service, 'is_trial_service': is_trial_service_, 'session': users.create_logout_url("/") if user else users.create_login_url("/"), "loading_enabled": loading_enabled, 'user_services': user_services, 'owning_user_services': owning_user_services, 'session_user': session_user, 'session_service_identity_user': session_service_identity_user, 'service_profile': None, 'email': self.request.get("email", None)} channel.append_firebase_params(template_params) if user: profile = get_service_or_user_profile(user) if is_service: if profile.tos_version != get_current_document_version(DOC_TERMS_SERVICE) and not profile.solution: logging.info('Redirecting to service terms and conditions page') self.redirect('/terms-and-conditions') return elif profile.tos_version != get_current_document_version(DOC_TERMS) and not profile.isCreatedForService: logging.info('Redirecting to user terms and conditions page') self.redirect('/terms-and-conditions') return else: profile = None if is_service: service_profile = profile template_params['service_profile'] = service_profile if not self.request.get('sp') and service_profile.solution: params = self.request.GET redirect_url = '/%s/' % service_profile.solution if params: params = dict((k, v.decode('utf8')) for k, v in params.iteritems()) redirect_url = "%s?%s" % (redirect_url, urllib.urlencode(params)) logging.info("Redirecting to url: %s" % redirect_url) self.redirect(redirect_url) return if user: if should_show_service_picker: page = "pick_account.html" else: page = "main.html" else: template_params["bg_image_uri"] = _get_front_page_image_by_ip(os.environ.get('HTTP_X_FORWARDED_FOR', None)) page = 'main_unauthenticated.html' path = os.path.join(os.path.dirname(__file__), page) self.response.out.write(template.render(path, template_params))
def ndb_get_service_menu_items(service_identity_user): svc_user = get_service_user_from_service_identity_user(service_identity_user) return NdbServiceMenuDef.list_by_service(svc_user)
def update_statistic(): # Completely rebuilds statistics on run. current_date = now() broadcast_count_dict = {} for news_item in get_news_of_last_month(): service_email = get_service_user_from_service_identity_user( news_item.sender).email() if service_email not in broadcast_count_dict: broadcast_count_dict[service_email] = 1 else: broadcast_count_dict[service_email] += 1 future_event_count_dict = {} for future_event_key in Event.get_future_event_keys(current_date): service_email = future_event_key.parent().name() if service_email not in future_event_count_dict: future_event_count_dict[service_email] = 1 else: future_event_count_dict[service_email] += 1 static_content_count_dict = {} for static_content_key in SolutionStaticContent.get_all_keys(): service_email = static_content_key.parent().name() if service_email not in static_content_count_dict: static_content_count_dict[service_email] = 1 else: static_content_count_dict[service_email] += 1 unanswered_question_count_dict = {} # find the oldest, unanswered question per customer and add it to the statistics for unanswered_question in SolutionInboxMessage.get_all_unanswered_questions( 5): service_email = unanswered_question.service_user.email() if unanswered_question.question_asked_timestamp != 0: if not service_email in unanswered_question_count_dict: unanswered_question_count_dict[ service_email] = unanswered_question.question_asked_timestamp elif unanswered_question.question_asked_timestamp < unanswered_question_count_dict[ service_email]: unanswered_question_count_dict[ service_email] = unanswered_question.question_asked_timestamp # dict with as keys the app id from the city, value the statistics of this city. statistics = {} for customer in Customer.all(): if len(customer.app_ids) != 0: service_email = customer.service_email if customer.app_id not in statistics: stats = AssociationStatistic(key_name=customer.app_id) stats.generated_on = current_date statistics[customer.app_id] = stats else: stats = statistics[customer.app_id] if not service_email: logging.error( u'Association customer %s(%d) has no service_email!', customer.name, customer.id) continue stats.customer_emails.append(service_email) if service_email in broadcast_count_dict: stats.broadcasts_last_month.append( broadcast_count_dict[customer.service_email]) else: stats.broadcasts_last_month.append(0) if service_email in future_event_count_dict: stats.future_events_count.append( future_event_count_dict[service_email]) else: stats.future_events_count.append(0) if service_email in static_content_count_dict: stats.static_content_count.append( static_content_count_dict[service_email]) else: stats.static_content_count.append(0) if service_email in unanswered_question_count_dict: stats.last_unanswered_questions_timestamps.append( unanswered_question_count_dict[service_email]) else: stats.last_unanswered_questions_timestamps.append(0) for chunk in chunks(statistics.values(), 200): db.put(chunk)