Пример #1
0
def test_form(service_user, form_id, testers):
    # type: (users.User, int, list[users.User]) -> None
    form = get_form(form_id, service_user)
    request = TestFormRequestTO(id=form_id, version=form.version)
    to_put = []
    prof = get_service_profile(service_user)
    branding = prof.broadcastBranding
    caption = localize(prof.defaultLanguage, 'forms.test_form')
    answers = [AnswerTO(id_=u'test',
                        caption=caption,
                        action=u'form://%d?version=%d&test=true' % (form_id, form.version))]
    flags = Message.FLAG_AUTO_LOCK
    alert_flags = Message.ALERT_FLAG_VIBRATE
    tag = None
    message = localize(prof.defaultLanguage, 'forms.click_button_to_test')
    for user_profile in get_profile_infos(testers):
        mobiles = db.get([get_mobile_key_by_account(mobile_detail.account) for mobile_detail in user_profile.mobiles])
        has_other = False
        android_mobile = None
        for mobile in mobiles:
            if mobile.is_android:
                android_mobile = mobile
            else:
                has_other = True
        if has_other:
            messaging.send(None, None, message, answers, flags, [MemberTO.from_user(user_profile.user)], branding, tag,
                           alert_flags=alert_flags)
        else:
            title = localize(prof.defaultLanguage, 'forms.test_form_x', title=form.title)
            body = localize(prof.defaultLanguage, 'forms.click_to_test_your_form')
            kwargs = {CAPI_KEYWORD_PUSH_DATA: TestFormNotification(title, body, form.id, form.version)}
            to_put.extend(testForm(test_form_response_handler, logError, user_profile.user, request=request,
                                   MOBILE_ACCOUNT=android_mobile, DO_NOT_SAVE_RPCCALL_OBJECTS=True, **kwargs))
    db.put(to_put)
def start_service_location_tracking(service_identity_user, app_user, until, distance_filter):
    from rogerthat.bizz.friends import areFriends
    service_profile_info, human_profile_info = get_profile_infos([service_identity_user, app_user])
    if not areFriends(service_profile_info, human_profile_info):
        raise CanOnlyTrackServiceSubscriptionsException()
    def trans():
        slt = get_current_tracker(app_user, service_identity_user)
        if slt:
            return slt.encrypted_key()
        key = ServiceLocationTracker.create_key(app_user, str(uuid.uuid4()))
        slt = ServiceLocationTracker(key=key, creation_time=now(), until=until, enabled=True,
                               service_identity_user=service_identity_user)
        slt.put()
        request = TrackLocationRequestTO()
        request.high_prio = True
        request.friend = remove_slash_default(service_identity_user).email()
        request.target = GetLocationRequestTO.TARGET_SERVICE_LOCATION_TRACKER
        request.until = until
        request.distance_filter = distance_filter
        for capi_call in trackLocation(track_location_response_handler, track_location_response_error_handler, app_user,
                                       request=request, DO_NOT_SAVE_RPCCALL_OBJECTS=True):
            capi_call.tracker = key
            capi_call.put()
        return slt.encrypted_key()
    xg_on = db.create_transaction_options(xg=True)
    return db.run_in_transaction_options(xg_on, trans)
def _send_notification_about_failed_location_fix(user, friend, friend_mobile_key_name, target, error_status):
    '''
    @param user: The user who sent the location request.
    @param friend: The user who failed to execute the location request.
    @param friend_mobile_key_name: The key name of the friend's Mobile model.
    @param target: The reason of the location request. One of GetLocationRequestTO.TARGET_*.
    @param error_status: The reason of the failed location request. One of GetLocationErrorTO.STATUS_*.
    '''
    friend_profile, user_profile = get_profile_infos([friend, user], expected_types=[UserProfile, UserProfile])
    app_name = get_app_name_by_id(user_profile.app_id)
    friend_msg = None
    user_reason_msg = None
    if error_status in (GetLocationErrorTO.STATUS_AUTHORIZATION_DENIED,
                        GetLocationErrorTO.STATUS_AUTHORIZATION_ONLY_WHEN_IN_USE):
        if error_status == GetLocationErrorTO.STATUS_AUTHORIZATION_DENIED:
            friend_msg = localize(friend_profile.language, "_location_services_denied",
                                  name=user_profile.name, app_name=app_name)
            user_reason_msg = localize(user_profile.language, "_friend_denied_location_services",
                                       name=friend_profile.name, app_name=app_name)
        elif error_status == GetLocationErrorTO.STATUS_AUTHORIZATION_ONLY_WHEN_IN_USE:
            friend_msg = localize(friend_profile.language, "_location_services_denied",
                                  name=user_profile.name, app_name=app_name)
            user_reason_msg = localize(user_profile.language, "_friend_denied_location_services",
                                       name=friend_profile.name, app_name=app_name)

        if friend_msg:
            friend_mobile = Mobile.get_by_key_name(friend_mobile_key_name)
            if friend_mobile.is_ios and friend_mobile.osVersion:
                if friend_mobile.osVersion.startswith('7'):
                    friend_msg += "\n\n" + localize(friend_profile.language, "_enable_location_services_ios7",
                                                    app_name=app_name)
                elif friend_mobile.osVersion.startswith('8'):
                    friend_msg += "\n\n" + localize(friend_profile.language, "_enable_location_services_ios8",
                                                    app_name=app_name)

    if target == GetLocationRequestTO.TARGET_MOBILE:
        user_msg = localize(user_profile.language,
                            "We could not determine the location of %(name)s.",
                            name=friend_profile.name)
    elif target == GetLocationRequestTO.TARGET_MOBILE_FIRST_REQUEST_AFTER_GRANT:
        user_msg = localize(user_profile.language,
                            "%(name)s accepted your location sharing request. Unfortunately we could not determine his/her location at this moment.",
                            name=friend_profile.name)
    else:
        logging.error("Don't know what to do in _send_notification_about_failed_location_fix.\n\nLocals:\n%s" % locals())
        return

    if user_reason_msg:
        user_msg = u"%s (%s)" % (user_msg, user_reason_msg)

    if user_msg and not friend_msg:
        user_msg = u"%s\n\n%s" % (user_msg, localize(user_profile.language, "Please try again later."))

    xg_on = db.create_transaction_options(xg=True)
    db.run_in_transaction_options(xg_on, dashboardNotification, user, user_msg)
    if friend_msg:
        db.run_in_transaction_options(xg_on, dashboardNotification, friend, friend_msg)
def restoreUserDataAfterReactivate(app_user):
    models_to_restore = list()
    archives_to_delete = list()

    for avatar_archive in AvatarArchive.all().filter("user ="******"user ="******"len(models_to_restore) %s %r", len(models_to_restore), models_to_restore)
    logging.info("len(archives_to_delete) %s %r", len(archives_to_delete), archives_to_delete)
    db.put(models_to_restore)
    db.delete(archives_to_delete)

    if not AuthorizedUser.all().filter(u"user =", app_user).get():
        au = AuthorizedUser()
        au.user = app_user
        au.put()

    if friend_map_archive:
        from rogerthat.bizz.friends import makeFriends

        # Skip friends that unsubscribed in the meantime
        cleanup_friend_map = False
        friend_profile_infos = get_profile_infos(friend_map.friends, allow_none_in_results=True)

        for friend_user, friendProfileInfo in zip(friend_map.friends, friend_profile_infos):
            if friendProfileInfo:
                continue
            logging.debug('User %s must have been deactivated in the mean while. Not executing makeFriends.',
                          friend_user.email())
            friend_map.friends.remove(friend_user)
            friend_map.friendDetails.remove(friend_user.email())
            cleanup_friend_map = True
        if cleanup_friend_map:
            friend_map.put()

        # MakeFriends of remaining users in friendMap
        for f in friend_map.friendDetails:
            connected_user = users.User(f.email)
            makeFriends(friend_map.user, connected_user, connected_user, servicetag=None, origin=None,
                        notify_invitee=False, notify_invitor=False, user_data=None)
def _create_unread_messages(stats, language, server_settings, user_profile):
    sender_users = list({s[0] for s in stats[1] if s[0] != MC_DASHBOARD})
    sender_profile_infos = dict(zip(sender_users, get_profile_infos(sender_users, allow_none_in_results=True)))

    timezone_diff = 0
    if user_profile.mobiles:
        for mobile_detail in user_profile.mobiles:
            mobile = Mobile.get(Mobile.create_key(mobile_detail.account))
            timezone_diff = mobile.timezoneDeltaGMT or 0
            break

    avatars = dict()  # { avatar_id : (avatar_data) }
    def get_avatar_url(avatar_id):
        avatar = avatars.get(avatar_id)
        if not avatar:
            if avatar_id in ('nuntiuz', 'unknown'):
                if avatar == 'nuntiuz':
                    avatar = UNKNOWN_AVATAR
                else:
                    avatar = NUNTIUZ_AVATAR
            else:
                avatar = get_avatar_cached(avatar_id, size=40)
            avatars[avatar_id] = avatar
        return 'cid:%s' % avatar_id

    unread_messages = list()  # sorted by message.creationTimestamp
    for sender_user, message, broadcast_type, creation_time in sorted(stats[1], key=lambda x: x[3]):
        sender_profile_info = sender_profile_infos.get(sender_user)
        if sender_profile_info:
            name = sender_profile_info.name
            avatar_url = get_avatar_url(sender_profile_info.avatarId)
        elif sender_user == MC_DASHBOARD:
            name = get_profile_info_name(sender_user, user_profile.app_id)
            avatar_url = get_avatar_url('nuntiuz')
        else:
            name = sender_user.email().split(':', 1)[0].split('/', 1)[0]
            avatar_url = get_avatar_url('unknown')

        creation_date_time = datetime.datetime.utcfromtimestamp(creation_time + timezone_diff)
        creation_time_str = '%s, %s' % (format_date(creation_date_time, locale=language, format='short'),
                                        format_time(creation_date_time, locale=language, format='short'))

        if broadcast_type:
            sender_user = add_slash_default(sender_user)

        if len(name) > 43:
            name = name[:40] + u'...'

        unread_messages.append(UnreadMessage(name, avatar_url, message, broadcast_type, creation_time_str,
                                             localize(language, 'email_reminder_unsubscribe_caption',
                                                      notification_type=xml_escape(broadcast_type) if broadcast_type else None,
                                                      service=xml_escape(name)),
                                             generate_unsubscribe_broadcast_link(user_profile.user, sender_user, name,
                                                                                 broadcast_type)))
    return unread_messages, avatars
Пример #6
0
    def testProfileCache(self):
        john = users.User(u"*****@*****.**")
        create_user_profile(john, u"John Doe")

        jane = users.User(u"*****@*****.**")
        create_user_profile(jane, u"John Doe")

        service = users.User(u"*****@*****.**")
        create_service_profile(service, u"Tha service")

        flush_request_cache()

        john_cache_key = _get_db_profile.cache_key(john)  # @UndefinedVariable
        jane_cache_key = _get_db_profile.cache_key(jane)  # @UndefinedVariable
        service_cache_key = _get_db_profile.cache_key(service)  # @UndefinedVariable
        assert MISSING == get_from_request_cache(john_cache_key)
        assert MISSING == get_from_request_cache(jane_cache_key)  # @UndefinedVariable
        assert MISSING == get_from_request_cache(service_cache_key)  # @UndefinedVariable

        get_user_profile(john)
        assert MISSING != get_from_request_cache(john_cache_key)

        rpc.wait_for_rpcs()

        memcache_result = memcache.get(john_cache_key)  # @UndefinedVariable
        buf = StringIO(memcache_result)
        success, result = _get_db_profile.deserializer(buf)  # @UndefinedVariable
        assert success
        assert result.user == john

        get_profile_infos([john, jane, service], False, False, expected_types=[
                          UserProfile, UserProfile, ServiceIdentity])

        assert MISSING != get_from_request_cache(john_cache_key)
        assert MISSING == get_from_request_cache(jane_cache_key)  # @UndefinedVariable
        assert MISSING == get_from_request_cache(service_cache_key)  # @UndefinedVariable

        get_profile_infos([john, jane, service], False, True, expected_types=[
                          UserProfile, UserProfile, ServiceIdentity])

        rpc.wait_for_rpcs()
Пример #7
0
 def fromServiceProfile(service_profile, broadcasts):
     to = ServiceBroadCastConfigurationTO()
     to.broadcast_types = service_profile.broadcastTypes
     user_profiles = get_profile_infos(service_profile.broadcastTestPersons,
                                       expected_types=len(service_profile.broadcastTestPersons) * [UserProfile],
                                       allow_none_in_results=True)
     to.test_persons = [UserDetailsTO.fromUserProfile(user_profile) for user_profile in filter(None, user_profiles)]
     to.broadcasts = map(BroadcastTO.fromBroadcast, broadcasts)
     to.warnings = list()
     if not get_broadcast_settings_items(service_profile.user, 1):
         to.warnings.append(u"There is no 'Broadcast settings' service menu item.")
     return to
Пример #8
0
def load_city_wide_lottery_detail_customer_points(city_app_id, email, app_id):
    app_user = create_app_user_by_email(email, app_id)
    visits = get_solution_city_wide_lottery_loyalty_visits_for_user(city_app_id, app_user)
    r = LoyaltyCustomerPointsTO()

    # XXX: don't use get_profile_infos
    profile_infos = get_profile_infos([app_user], allow_none_in_results=True)
    for app_user, profile_info in zip([app_user], profile_infos):
        if not profile_info or profile_info.isServiceIdentity:
            continue
        r.user_details = ExtendedUserDetailsTO.fromUserProfile(profile_info, None)
        app_info = get_app_info_cached(r.user_details.app_id)
        r.user_details.app_name = app_info.name
    r.visits = [SolutionLoyaltyVisitTO.fromModel(visit) for visit in visits]
    return r
def update_location(app_user, service_identity_user, slt_key):
    from rogerthat.bizz.friends import areFriends
    slt = db.get(slt_key)
    if not slt or not slt.enabled or slt.until < now():
        return
    service_profile_info, human_profile_info = get_profile_infos([service_identity_user, app_user])
    if not areFriends(service_profile_info, human_profile_info):
        return
    request = GetLocationRequestTO()
    request.high_prio = True
    request.friend = service_identity_user.email()
    request.target = GetLocationRequestTO.TARGET_SERVICE_LOCATION_TRACKER
    for capi_call in getLocation(get_location_response_handler, dismissError, app_user, request=request, DO_NOT_SAVE_RPCCALL_OBJECTS=True):
        capi_call.tracker = slt_key
        capi_call.put()
Пример #10
0
def load_city_wide_lottery_customer_points(city_app_id, cursor=None):

    result_dict = dict()
    qry = SolutionCityWideLotteryVisit.load(city_app_id)
    qry.with_cursor(cursor)
    visits = qry.fetch(10)
    cursor_ = qry.cursor()
    has_more = False
    if len(visits) != 0:
        qry.with_cursor(cursor_)
        if len(qry.fetch(1)) > 0:
            has_more = True

    for visit in visits:
        saved_points = result_dict.get(visit.app_user)
        if not saved_points:
            result_dict[visit.app_user] = saved_points = LoyaltyCustomerPointsTO()
            saved_points.visits = []

        saved_points.visits.append(SolutionLoyaltyVisitTO.fromModel(visit))

    # XXX: don't use get_profile_infos
    app_users = result_dict.keys()
    profile_infos = get_profile_infos(app_users, allow_none_in_results=True)
    for app_user, profile_info in zip(app_users, profile_infos):
        if not profile_info or profile_info.isServiceIdentity:
            logging.info('User %s not found', app_user.email())
            del result_dict[app_user]
            continue
        saved_points = result_dict[app_user]
        saved_points.user_details = ExtendedUserDetailsTO.fromUserProfile(profile_info, None)
        app_info = get_app_info_cached(saved_points.user_details.app_id)
        saved_points.user_details.app_name = app_info.name
        saved_points.visits = sorted(saved_points.visits,
                                     key=lambda x: -x.timestamp)

    r = BaseLoyaltyCustomersTO()
    r.loyalty_type = SolutionLoyaltySettings.LOYALTY_TYPE_LOTTERY
    r.cursor = cursor_.decode("utf8")
    r.has_more = has_more
    r.customers = sorted(result_dict.itervalues(),
                         key=lambda x: -x.visits[0].timestamp)
    return r
Пример #11
0
def _send_message_to_inform_user_about_a_new_join_step_2(fb_friend_user, new_user):
    new_user_profile, fb_friend_profile = get_profile_infos([new_user, fb_friend_user], expected_types=[UserProfile, UserProfile])
    azzert(new_user_profile.app_id == fb_friend_profile.app_id)
    app_name = get_app_name_by_id(new_user_profile.app_id)
    to_language = fb_friend_profile.language if fb_friend_profile else DEFAULT_LANGUAGE
    message_text = localize(to_language, "%(name)s just joined %(app_name)s, and we found you in his facebook friends list!", name=new_user_profile.name, app_name=app_name)
    button = ButtonTO()
    button.id = INVITE_ID
    button.caption = localize(to_language, "Invite %(name)s to connect on %(app_name)s", name=new_user_profile.name, app_name=app_name)
    button.action = None
    button.ui_flags = 0
    def trans():
        message = sendMessage(MC_DASHBOARD, [UserMemberTO(fb_friend_user)], Message.FLAG_ALLOW_DISMISS, 0, None,
                              message_text, [button], None, get_app_by_user(fb_friend_user).core_branding_hash,
                              INVITE_FACEBOOK_FRIEND, is_mfr=False)
        message.invitor = fb_friend_user
        message.invitee = new_user
        message.put()
    xg_on = db.create_transaction_options(xg=True)
    db.run_in_transaction_options(xg_on, trans)
Пример #12
0
def add_loyalty_scan(key, loyalty_type, value):
    service_user = users.get_current_user()
    try:
        sls = SolutionLoyaltyScan.get(key)
        if sls is None:
            raise BusinessException("Could not find scan")
        if sls.processed:
            raise BusinessException("Scan was already processed")

        if sls.app_user_info:
            user_details = UserDetailsTO()
            user_details.email = sls.app_user_info.email
            user_details.name = sls.app_user_info.name
            user_details.language = sls.app_user_info.language
            user_details.avatar_url = sls.app_user_info.avatar_url
            user_details.app_id = sls.app_user_info.app_id
        else:
            # XXX: don't use get_profile_infos
            profile_info = get_profile_infos([sls.app_user], allow_none_in_results=True)[0]
            if not profile_info or profile_info.isServiceIdentity:
                user_details = None
            else:
                user_details = UserDetailsTO.fromUserProfile(profile_info)

        jsondata = {}
        jsondata['loyalty_type'] = loyalty_type
        if loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_REVENUE_DISCOUNT:
            jsondata['price'] = value
        else:
            jsondata['count'] = value
        success, _, _ = add_loyalty_for_user(
            service_user, sls.service_identity, sls.admin_user, sls.app_user, jsondata, now(), user_details)
        if not success:
            raise BusinessException("error-occured-unknown")

        sls.processed = True
        sls.put()
        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        sln_settings = get_solution_settings(service_user)
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Пример #13
0
def list_friends(service_identity=None, cursor=None, app_id=None, batch_count=100):
    from rogerthat.bizz.service import get_and_validate_service_identity_user, valididate_app_id_for_service_identity_user
    from rogerthat.dal.service import get_users_connected_to_service_identity

    bizz_check(batch_count <= 1000, "Cannot batch more than 1000 friends at once.")

    service_identity_user = get_and_validate_service_identity_user(users.get_current_user(), service_identity)
    if app_id:
        valididate_app_id_for_service_identity_user(service_identity_user, app_id)
    if cursor:
        try:
            cursor = decrypt(service_identity_user, cursor)
        except:
            from rogerthat.bizz.exceptions import InvalidCursorException
            raise InvalidCursorException()
    fsics, cursor = get_users_connected_to_service_identity(service_identity_user, cursor, batch_count, app_id)
    # prevent extra roundtrip by trying to detect whether there are more results to fetch
    if len(fsics) < batch_count and cursor:
        extra_fsics, _ = get_users_connected_to_service_identity(service_identity_user, cursor, 1, app_id)
        if len(extra_fsics) == 0:
            cursor = None
    result = FriendListResultTO()
    result.cursor = unicode(encrypt(service_identity_user, cursor)) if cursor else None
    result.friends = list()

    user_profiles = get_profile_infos([fsic.friend for fsic in fsics], expected_types=[UserProfile] * len(fsics))
    app_names = {}
    for user_profile, fsic in zip(user_profiles, fsics):
        svc_friend = ServiceFriendTO()
        human_user, svc_friend.app_id = get_app_user_tuple(fsic.friend)
        svc_friend.avatar = u"%s/unauthenticated/mobi/cached/avatar/%s" % (get_server_settings().baseUrl, fsic.friend_avatarId)
        svc_friend.email = human_user.email()
        svc_friend.language = user_profile.language
        svc_friend.name = fsic.friend_name
        if svc_friend.app_id not in app_names:
            app = get_app_by_id(svc_friend.app_id)
            app_names[svc_friend.app_id] = app.name

        svc_friend.app_name = app_names[svc_friend.app_id]
        result.friends.append(svc_friend)
    return result
Пример #14
0
 def run():
     targets = _validate_capi_call(result_f, error_f, target, alias, f, accept_sub_types=accept_sub_types)
     if not targets:
         return
     cc = dict()
     cc[API_VERSION] = 1
     cc[FUNCTION] = alias
     cc[PARAMETERS] = dict(map(lambda (arg, type_): (arg, serialize_value(kwargs[arg], *get_type_details(type_))), f.meta["kwarg_types"].iteritems()))
     skippers = kwargs.get(SKIP_ACCOUNTS) or list()
     mobile = kwargs.get(MOBILE_ACCOUNT)
     if mobile:
         from rogerthat.models.properties.profiles import MobileDetail
         mobile_detail = MobileDetail()
         mobile_detail.account = mobile.account
         mobile_detail.type_ = mobile.type
         mobile_detail.pushId = mobile.pushId
         mobile_detail.app_id = mobile.app_id
         logging.info(u"Sending capi: %s call to %s" % (alias, mobile.user.email()))
         logging.info(u"Sending to account %s" % mobile_detail.account)
         yield _send_client_call(mobile_detail, cc, mobile.user, alias)
     else:
         from rogerthat.dal.profile import get_profile_infos
         profile_infos = get_profile_infos(targets, allow_none_in_results=True)
         for profile_info in profile_infos:
             if not profile_info:
                 continue
             if profile_info.isServiceIdentity:
                 logging.warn("Not sending capi call to ServiceIdentity (%s)" % profile_info.user.email())
             else:
                 if profile_info.mobiles is None:
                     logging.info(u"%s does not have mobiles registered" % profile_info.user.email())
                     continue
                 for mobile_detail in profile_info.mobiles:
                     if mobile_detail.account in skippers:
                         logging.info(u"Skipping account %s " % mobile_detail.account)
                         continue
                     logging.info(u"Sending capi: %s call to %s, account: %s" % (alias, profile_info.user.email(), mobile_detail.account))
                     yield _send_client_call(mobile_detail, cc, profile_info.user, alias)
Пример #15
0
def load_detail_customer_points(loyalty_type, email, app_id):
    service_user = users.get_current_user()
    session_ = users.get_current_session()
    service_identity = session_.service_identity
    app_user = create_app_user_by_email(email, app_id)
    if loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_REVENUE_DISCOUNT:
        visits = get_solution_loyalty_visits_for_revenue_discount(service_user, service_identity, app_user)
    elif loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_LOTTERY:
        visits = get_solution_loyalty_visits_for_lottery(service_user, service_identity, app_user)
    else:
        visits = get_solution_loyalty_visits_for_stamps(service_user, service_identity, app_user)

    r = LoyaltyCustomerPointsTO()

    # XXX: don't use get_profile_infos
    profile_infos = get_profile_infos([app_user], allow_none_in_results=True)
    for app_user, profile_info in zip([app_user], profile_infos):
        if not profile_info or profile_info.isServiceIdentity:
            continue
        r.user_details = ExtendedUserDetailsTO.fromUserProfile(profile_info, None)
        app_info = get_app_info_cached(r.user_details.app_id)
        r.user_details.app_name = app_info.name
    r.visits = [SolutionLoyaltyVisitTO.fromModel(visit) for visit in visits]
    return r
Пример #16
0
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):
    from rogerthat.rpc.calls import HIGH_PRIORITY
    _validate_start_flow(service_identity_user, thread_key, members, tag=tag)
    service_user = get_service_user_from_service_identity_user(service_identity_user)

    js_flow_dict = generate_js_flow(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

    profile_infos = {profile_info.user: profile_info for profile_info in get_profile_infos(members + [service_identity_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:
                    raise InvalidMessageFlowLanguageException(json.dumps(js_flow_dict.keys()), target_language)

            flow_definition, brandings, attachments = js_flow_dict[target_language]

        force_skip_attachments_download = False
        if push_message:
            for mobile_detail in profile_infos[app_user].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
        startFlow(start_flow_response_handler, logError, app_user, request=request)

        if push_message:
            sender_name = _ellipsize_for_json(profile_infos[service_identity_user].name, 30, cut_on_spaces=False)

            for mobile_detail in profile_infos[app_user].mobiles:
                if mobile_detail.type_ == Mobile.TYPE_IPHONE_HTTP_APNS_KICK and mobile_detail.pushId:
                    cbd = dict(r=mobile_detail.account,
                               p=HIGH_PRIORITY,
                               t=["apns"],
                               kid=str(uuid.uuid4()),
                               a=mobile_detail.app_id)
                    cbd['d'] = mobile_detail.pushId
                    cbd['m'] = base64.encodestring(construct_push_notification('NM', [sender_name, push_message], 'n.aiff',
                                                                               lambda args, too_big: [sender_name, _ellipsize_for_json(args[1], _len_for_json(args[1]) - too_big)]))
                    logging.debug('Sending push notification along with start_local_flow.\n%s', cbd)
                    kicks.append(json.dumps(cbd))

    return message_flow_run_id
Пример #17
0
            def run():
                def _should_send_capi_call_to_mobile(feature_version, mobile):
                    if not feature_version or DEBUG:
                        return True

                    if mobile.is_ios:
                        version = feature_version.ios
                    elif mobile.is_android:
                        version = feature_version.android
                    else:
                        version = None

                    if version:
                        from rogerthat.bizz.features import Version
                        mobile_settings = get_mobile_settings_cached(mobile)
                        if not mobile_settings:
                            return False

                        if Version(mobile_settings.majorVersion, mobile_settings.minorVersion) < version:
                            return False

                    return True


                targets = _validate_capi_call(result_f, error_f, target, alias, f, accept_sub_types=accept_sub_types)
                if not targets:
                    return
                cc = dict()
                cc[API_VERSION] = 1
                cc[FUNCTION] = alias
                cc[PARAMETERS] = {arg: serialize_value(kwargs[arg], *get_type_details(type_, kwargs[arg]))
                                  for arg, type_ in f.meta["kwarg_types"].iteritems()}
                skippers = kwargs.get(SKIP_ACCOUNTS) or list()
                mobile = kwargs.get(MOBILE_ACCOUNT)

                if mobile:
                    from rogerthat.models.properties.profiles import MobileDetail

                    if not _should_send_capi_call_to_mobile(feature_version, mobile):
                        logging.debug(u'%s is not supported by mobile %s of user %s',
                                      alias, mobile.account, mobile.user.email())
                        return

                    mobile_detail = MobileDetail()
                    mobile_detail.account = mobile.account
                    mobile_detail.type_ = mobile.type
                    mobile_detail.pushId = mobile.pushId
                    mobile_detail.app_id = mobile.app_id
                    logging.info(u"Sending capi: %s call to %s" % (alias, mobile.user.email()))
                    logging.info(u"Sending to account %s" % mobile_detail.account)
                    yield _send_client_call(mobile_detail, cc, mobile.user, alias)
                else:
                    from rogerthat.dal.profile import get_profile_infos
                    from rogerthat.dal.mobile import get_mobile_key_by_account

                    profile_infos = get_profile_infos(targets, allow_none_in_results=True)
                    for profile_info in profile_infos:
                        if not profile_info:
                            continue
                        if profile_info.isServiceIdentity:
                            logging.warn(u"Not sending capi call to ServiceIdentity (%s)" % profile_info.user.email())
                        else:
                            if profile_info.mobiles is None:
                                logging.info(u"%s does not have mobiles registered" % profile_info.user.email())
                                continue

                            mobiles = db.get([get_mobile_key_by_account(mobile_detail.account) for mobile_detail in profile_info.mobiles])
                            for mobile_detail, mobile in zip(profile_info.mobiles, mobiles):
                                if mobile_detail.account in skippers:
                                    logging.info(u"Skipping account %s " % mobile_detail.account)
                                    continue
                                if not _should_send_capi_call_to_mobile(feature_version, mobile):
                                    logging.debug(u'%s is not supported by mobile %s of user %s',
                                                  alias, mobile.account, mobile.user.email())
                                    continue
                                logging.info(u"Sending capi: %s call to %s, account: %s" % (alias, profile_info.user.email(), mobile_detail.account))
                                yield _send_client_call(mobile_detail, cc, profile_info.user, alias)
Пример #18
0
def load_customer_points(loyalty_type=None, cursor=None):
    service_user = users.get_current_user()
    session_ = users.get_current_session()
    service_identity = session_.service_identity
    loyalty_settings = SolutionLoyaltySettings.get_by_user(service_user)
    if not loyalty_type:
        loyalty_type = loyalty_settings.loyalty_type
    result_dict = dict()
    visits = []
    cursor_ = None
    has_more = False
    if loyalty_type in SolutionLoyaltySettings.LOYALTY_TYPE_MAPPING:
        qry = SolutionLoyaltySettings.LOYALTY_TYPE_MAPPING[loyalty_type].load(service_user, service_identity)
        qry.with_cursor(cursor)
        visits = qry.fetch(10)
        cursor_ = qry.cursor()
        if len(visits) != 0:
            qry.with_cursor(cursor_)
            if len(qry.fetch(1)) > 0:
                has_more = True

    for visit in visits:
        saved_points = result_dict.get(visit.app_user)
        if not saved_points:
            result_dict[visit.app_user] = saved_points = LoyaltyCustomerPointsTO()
            saved_points.visits = []

        saved_points.visits.append(SolutionLoyaltyVisitTO.fromModel(visit))

    # XXX: don't use get_profile_infos
    app_users = result_dict.keys()
    profile_infos = get_profile_infos(app_users, allow_none_in_results=True)
    for app_user, profile_info in zip(app_users, profile_infos):
        if not profile_info or profile_info.isServiceIdentity:
            logging.info('User %s not found', app_user.email())
            del result_dict[app_user]
            continue
        saved_points = result_dict[app_user]
        saved_points.user_details = ExtendedUserDetailsTO.fromUserProfile(profile_info, None)
        app_info = get_app_info_cached(saved_points.user_details.app_id)
        saved_points.user_details.app_name = app_info.name
        saved_points.visits = sorted(saved_points.visits,
                                     key=lambda x: -x.timestamp)

    r = LoyaltyCustomersTO()
    r.cursor = cursor_.decode("utf8") if cursor_ else None
    r.has_more = has_more
    r.loyalty_type = loyalty_type
    if loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_REVENUE_DISCOUNT:
        r.loyalty_settings = LoyaltyRevenueDiscountSettingsTO.fromModel(loyalty_settings)
    elif loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_LOTTERY:
        r.loyalty_settings = LoyaltyLotterySettingsTO.fromModel(loyalty_settings)
    elif loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_STAMPS:
        r.loyalty_settings = LoyaltyStampsSettingsTO.fromModel(loyalty_settings)
    elif loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_CITY_WIDE_LOTTERY:
        r.loyalty_settings = LoyaltyCityWideLotterySettingsTO.fromModel(loyalty_settings)
    else:
        r.loyalty_settings = None
    r.customers = sorted(result_dict.itervalues(),
                         key=lambda x: -x.visits[0].timestamp)

    return r
Пример #19
0
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
Пример #20
0
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
Пример #21
0
def _pick_winner(service_user, sln_loyalty_lottery_key):
    now_ = now()
    sln_loyalty_lottery = db.get(sln_loyalty_lottery_key)
    if sln_loyalty_lottery.claimed or sln_loyalty_lottery.redeemed or sln_loyalty_lottery.deleted:
        return
    if sln_loyalty_lottery.schedule_loot_time > 0:
        return
    service_identity = sln_loyalty_lottery.service_identity
    service_identity_user = create_service_identity_user_wo_default(
        service_user, service_identity)
    sls_key = SolutionLoyaltySettings.create_key(service_user)
    slls_key = SolutionLoyaltyLotteryStatistics.create_key(
        service_user, service_identity)
    sln_settings_key = SolutionSettings.create_key(service_user)
    sln_loyalty_settings, slls, sln_settings = db.get(
        [sls_key, slls_key, sln_settings_key])

    if sln_loyalty_settings.loyalty_type != SolutionLoyaltySettings.LOYALTY_TYPE_LOTTERY:
        sln_loyalty_lottery.deleted = True
        sln_loyalty_lottery.put()
        return

    logging.info("loyalty lottery loot: %s", service_user)
    possible_winners = []

    if slls:
        for i, app_user in enumerate(slls.app_users):
            if app_user not in sln_loyalty_lottery.skip_winners and app_user != sln_loyalty_lottery.winner:
                for i in xrange(slls.count[i]):
                    possible_winners.append(app_user)

    logging.debug("possible winners count: %s", len(possible_winners))

    if len(possible_winners) == 0:
        if sln_loyalty_lottery.winner:
            logging.debug("can not assign winner, keep old")
        else:
            logging.debug("can not assign winner, delete lottery")
            sln_loyalty_lottery.deleted = True
            sln_loyalty_lottery.put()
        return

    else:
        winner = random.choice(possible_winners)
        logging.debug("new winner: %s", winner)

    slvl = SolutionLoyaltyVisitLottery.all() \
        .ancestor(parent_key_unsafe(service_identity_user, SOLUTION_COMMON)) \
        .filter('redeemed =', False) \
        .filter('app_user ='******'t use get_profile_infos
        profile_info = get_profile_infos([slvl.app_user],
                                         allow_none_in_results=True)[0]
        if not profile_info or profile_info.isServiceIdentity:
            azzert(False, "profile_info for app_user %s not found!" % winner)
        else:
            user_detail = UserDetailsTO.fromUserProfile(profile_info)

    loot_datetime_tz = datetime.fromtimestamp(
        sln_loyalty_lottery.end_timestamp,
        pytz.timezone(sln_settings.timezone))
    loot_date_str = format_datetime(loot_datetime_tz,
                                    format='medium',
                                    locale=sln_settings.main_language
                                    or DEFAULT_LANGUAGE)

    next_datetime_tz = datetime.fromtimestamp(
        now() + 24 * 3600, pytz.timezone(sln_settings.timezone))
    next_date_str = format_datetime(next_datetime_tz,
                                    format='medium',
                                    locale=sln_settings.main_language
                                    or DEFAULT_LANGUAGE)

    msg_ok = translate(sln_settings.main_language,
                       SOLUTION_COMMON,
                       'loyalty-lottery-loot-ok',
                       name=user_detail.name,
                       date_loot=loot_date_str,
                       price=sln_loyalty_lottery.winnings,
                       date=next_date_str)
    msg_sorry = translate(sln_settings.main_language, SOLUTION_COMMON,
                          'loyalty-lottery-loot-nok')

    btn = AnswerTO()
    btn.id = u'%s' % json.dumps({"key": unicode(sln_loyalty_lottery_key)})
    btn.type = u'button'
    btn.caption = translate(sln_settings.main_language, SOLUTION_COMMON,
                            'Confirm')
    btn.action = None
    btn.ui_flags = 0

    message_flags = Message.FLAG_ALLOW_DISMISS

    sln_i_settings = get_solution_settings_or_identity_settings(
        sln_settings, service_identity)

    def trans():
        sm_data = []

        if sln_loyalty_lottery.winner_timestamp != 0:
            logging.debug("loyalty lottery loot: update winner %s",
                          sln_loyalty_lottery.winner)
            sim_parent, _ = add_solution_inbox_message(
                service_user,
                sln_loyalty_lottery.solution_inbox_message_key,
                True,
                None,
                now_,
                msg_sorry,
                mark_as_read=True)
            if sim_parent.message_key_by_tag:
                message_key_by_tag = json.loads(sim_parent.message_key_by_tag)
                if message_key_by_tag.get(u"loyalty_lottery_loot", None):
                    deferred.defer(_messaging_seal,
                                   service_user,
                                   message_key_by_tag[u"loyalty_lottery_loot"],
                                   sim_parent.message_key,
                                   sim_parent.message_key,
                                   1,
                                   _transactional=True)

            send_inbox_forwarders_message(
                service_user,
                service_identity,
                None,
                msg_sorry, {
                    'if_name': user_detail.name,
                    'if_email': user_detail.email
                },
                message_key=sim_parent.solution_inbox_message_key,
                reply_enabled=sim_parent.reply_enabled,
                send_reminder=False)

            deferred.defer(send_email_to_user_for_loyalty_update, service_user,
                           service_identity, sln_loyalty_lottery.winner,
                           msg_sorry, False)
            sm_data.append({
                u"type":
                u"solutions.common.messaging.update",
                u"message":
                serialize_complex_value(
                    SolutionInboxMessageTO.fromModel(sim_parent, sln_settings,
                                                     sln_i_settings, True),
                    SolutionInboxMessageTO, False)
            })

        logging.debug("loyalty lottery loot: new winner %s", winner)

        sim_parent = create_solution_inbox_message(
            service_user,
            service_identity,
            SolutionInboxMessage.CATEGORY_LOYALTY,
            unicode(sln_loyalty_lottery_key),
            True, [user_detail],
            now_,
            msg_ok,
            True,
            mark_as_read=True)

        sln_loyalty_lottery.solution_inbox_message_key = sim_parent.solution_inbox_message_key

        if sln_loyalty_lottery.winner:
            if not sln_loyalty_lottery.skip_winners:
                sln_loyalty_lottery.skip_winners = []
            sln_loyalty_lottery.skip_winners.append(sln_loyalty_lottery.winner)
        sln_loyalty_lottery.pending = False
        sln_loyalty_lottery.winner = winner
        sln_loyalty_lottery.winner_info = SolutionUser.fromTO(
            user_detail) if user_detail else None
        sln_loyalty_lottery.winner_timestamp = now_
        sln_loyalty_lottery.put()

        send_inbox_forwarders_message(
            service_user,
            service_identity,
            None,
            msg_ok, {
                'if_name': user_detail.name,
                'if_email': user_detail.email
            },
            message_key=sim_parent.solution_inbox_message_key,
            reply_enabled=sim_parent.reply_enabled,
            send_reminder=False,
            answers=[btn],
            store_tag=u"loyalty_lottery_loot",
            flags=message_flags)

        deferred.defer(send_email_to_user_for_loyalty_update, service_user,
                       service_identity, sln_loyalty_lottery.winner, msg_ok,
                       False, sim_parent.solution_inbox_message_key)
        sm_data.append({
            u"type":
            u"solutions.common.messaging.update",
            u"message":
            serialize_complex_value(
                SolutionInboxMessageTO.fromModel(sim_parent, sln_settings,
                                                 sln_i_settings, True),
                SolutionInboxMessageTO, False)
        })
        sm_data.append({u"type": u"solutions.common.loyalty.lottery.update"})
        send_message(service_user, sm_data, service_identity=service_identity)

        deferred.defer(_continue,
                       service_user,
                       service_identity,
                       sln_loyalty_lottery_key,
                       _transactional=True)

    xg_on = db.create_transaction_options(xg=True)
    db.run_in_transaction_options(xg_on, trans)
Пример #22
0
def _pick_city_wide_lottery_winner(service_user, sln_cwl_lottery_key):
    sln_cwl = db.get(sln_cwl_lottery_key)
    if sln_cwl.winners:
        return
    slls = db.get(SolutionCityWideLotteryStatistics.create_key(sln_cwl.app_id))
    logging.info("city wide lottery loot: %s", sln_cwl.app_id)
    possible_winners = []

    if slls:
        for i, app_user in enumerate(slls.app_users):
            if app_user not in sln_cwl.skip_winners and app_user not in sln_cwl.winners:
                for i in xrange(slls.count[i]):
                    possible_winners.append(app_user)

    logging.debug("possible winners count: %s", len(possible_winners))

    if len(possible_winners) == 0:
        if sln_cwl.winners:
            logging.debug("can not assign winners, keep old")
        else:
            logging.debug("can not assign winners, delete city wide lottery")
            sln_cwl.deleted = True
            sln_cwl.put()
        return
    else:
        winners_needed = sln_cwl.x_winners
        logging.debug("winners_needed: %s", winners_needed)
        if len(possible_winners) < winners_needed:
            winners_needed = len(possible_winners)

        winners = []
        while True:
            if not possible_winners:
                break
            if len(winners) >= winners_needed:
                break
            winner = random.choice(possible_winners)
            possible_winners = filter(lambda a: a != winner, possible_winners)
            winners.append(winner)

    sln_settings = get_solution_settings(service_user)
    winners_info = []
    slvl_parent_key = SolutionCityWideLotteryVisit.create_city_parent_key(
        sln_cwl.app_id)
    winner_text = ""
    for winner in winners:
        slvl = SolutionCityWideLotteryVisit.all() \
            .ancestor(slvl_parent_key) \
            .filter('redeemed =', False) \
            .filter('app_user ='******'t use get_profile_infos
            profile_info = get_profile_infos([slvl.app_user],
                                             allow_none_in_results=True)[0]
            if not profile_info or profile_info.isServiceIdentity:
                continue
            else:
                eud = ExtendedUserDetailsTO.fromUserProfile(profile_info, None)

        with set_user(service_user):
            app_info = get_app_info_cached(eud.app_id)
        eud.app_name = app_info.name
        eud.public_key = None
        eud.public_keys = []
        winners_info.append(eud)

        winner_text = winner_text + "\n - %s (%s)" % (eud.name, eud.email)

    def trans():
        sln_cwl.pending = False
        sln_cwl.winners = winners
        sln_cwl.winners_info = json.dumps(
            serialize_complex_value(winners_info, ExtendedUserDetailsTO, True))
        sln_cwl.put()
        deferred.defer(_redeem_city_wide_lottery_visits,
                       service_user,
                       sln_cwl_lottery_key,
                       now(),
                       _transactional=True)

        to_emails = sln_settings.inbox_mail_forwarders
        if to_emails:
            solution_server_settings = get_solution_server_settings()
            subject = 'Winnaars gemeentelijke tombola'
            body = """Beste,
Volgende mensen hebben gewonnen met de tombola: %s


Met vriendelijke groeten,

Het Onze Stad App Team
""" % winner_text

            send_mail(solution_server_settings.shop_export_email, to_emails,
                      subject, body)

    xg_on = db.create_transaction_options(xg=True)
    db.run_in_transaction_options(xg_on, trans)
def post(app_user, location, timestamp, recipients):
    def parse_location(friend_language, accuracy, geocoded_results):
        # See https://developers.google.com/maps/documentation/geocoding/#Results
        if accuracy < 100:
            for result in results:
                if "street_address" in result["types"]:
                    return "\n" + localize(friend_language, "Location: %(address)s", address=result["formatted_address"])
            return "\n" + localize(friend_language, "Location: %(address)s", address=results[0]["formatted_address"])

        address_types = ["neighborhood", "sublocality", "locality", "political", "route"]
        for adt in address_types:
            for result in results:
                if adt in result["types"]:
                    return "\n" + localize(friend_language, "Location: %(address)s", address=result["formatted_address"])
        logging.error("Could not parse geo-coded result!")

    loc = GeoPointWithTimestampTO()
    loc.latitude = location.latitude
    loc.longitude = location.longitude
    loc.accuracy = location.accuracy
    loc.timestamp = timestamp

    maps_lat = loc.latitude / 1000000.0
    maps_long = loc.longitude / 1000000.0

    current_user, app_id = get_app_user_tuple(app_user)

    for recipient in (r for r in recipients if r.target == GetLocationRequestTO.TARGET_SERVICE_LOCATION_TRACKER):
        location_with_timestamp = GeoPointWithTimestampTO()
        location_with_timestamp.latitude = location.latitude
        location_with_timestamp.longitude = location.longitude
        location_with_timestamp.accuracy = location.accuracy
        location_with_timestamp.timestamp = timestamp
        handle_service_tracker_results(app_user, add_slash_default(users.User(recipient.friend)), location_with_timestamp)

    to_put = []
    for recipient in (r for r in recipients if r.target in (GetLocationRequestTO.TARGET_MOBILE, GetLocationRequestTO.TARGET_MOBILE_FIRST_REQUEST_AFTER_GRANT)):
        friend_user = create_app_user(users.User(recipient.friend), app_id)
        def trans():
            lr = LocationRequest.get_by_key_name(friend_user.email(), parent=parent_key(app_user))
            if not lr:
                return False
            lr.delete()
            return True
        if not db.run_in_transaction(trans):
            continue

        profile, friend_profile = get_profile_infos([app_user, friend_user], expected_types=[UserProfile, UserProfile])
        if recipient.target == GetLocationRequestTO.TARGET_MOBILE:
            m = localize(friend_profile.language, """Received location of %(name)s.

Accuracy: %(accuracy)sm""", name=profile.name, accuracy=loc.accuracy)
        else:
            m = localize(friend_profile.language, """%(name)s accepted your location sharing request.
Latest information:

Accuracy: %(accuracy)sm""", name=profile.name, accuracy=loc.accuracy)
        url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=%s,%s&sensor=true" % (maps_lat, maps_long)
        logging.info("Fetching URL: %s" % url)
        result = urlfetch.fetch(url)
        logging.info("Fetched result: %s" % result.content)
        logging.info("Result status code: %s" % result.status_code)
        if result.status_code == 200:
            results = json.loads(result.content)
            if results["status"] == "OK" and results["results"]:
                results = results["results"]
                location = parse_location(friend_profile.language, loc.accuracy, results)
                if location:
                    m += location
        button = ButtonTO()
        button.id = u"show_map"
        button.caption = localize(friend_profile.language, "Show map")
        button.action = u"geo://%s,%s" % (str(maps_lat).replace(',', '.'), str(maps_long).replace(',', '.'))
        button.ui_flags = 0
        msg_model = sendMessage(MC_DASHBOARD, [UserMemberTO(friend_user)], Message.FLAG_ALLOW_DISMISS, 0, None, m,
                                [button], None, get_app_by_user(friend_user).core_branding_hash, None, is_mfr=False)
        to_put.append(LocationMessage(key=LocationMessage.create_key(app_user, msg_model.key().name()),
                                      receiver=recipient.friend))
    ndb.put_multi(to_put)
    mobile_recipients = [create_app_user(users.User(r.friend), app_id) for r in recipients if r.target == GetLocationRequestTO.TARGET_MOBILE_FRIENDS_ON_MAP]
    request = LocationResultRequestTO()
    request.friend = current_user.email()
    request.location = loc
    locationResult(get_location_result_response_handler, logError, mobile_recipients, request=request)
    web_recipients = [r for r in recipients if r.target == GetLocationRequestTO.TARGET_WEB]
    for recipient in web_recipients:
        friend_user = create_app_user(users.User(recipient.friend), app_id)
        channel.send_message(friend_user, 'rogerthat.location.location_response', friend=current_user.email(), location=serialize_complex_value(loc, GeoPointWithTimestampTO, False))