Beispiel #1
0
def test_translate_for_user():
    user = User("testtest")
    user.locale = "en_US"
    uc = UserContext(user)
    assert uc._("New Chat") == "New Chat"
    user.locale = "fr_FR"
    assert uc._("New Chat") == "Nouveau chat"
    user.locale = "ar_AR"
    assert uc._("New Chat") == "دردشة جديدة"
Beispiel #2
0
def test_on_match_end(mocker, monkeypatch):
    fix_matcher_rand(mocker)
    delegate = UserStateDelegate()
    user = User.create("test1",
                       finding_genders="female",
                       gender="male",
                       points=30)
    partner = User.create("test2",
                          finding_genders="female,male",
                          gender="female",
                          points=30)
    time = datetime.datetime.utcnow()
    record = MatchingQueue(created_at=time, finding_genders="male,female")
    uc, pc = [UserContext(u) for u in [user, partner]]
    delegate.on_found_partner(uc, pc, record)

    delegate.on_speak(uc)
    delegate.on_speak(uc)
    delegate.on_speak(pc)

    delegate.on_match_ended(uc, pc)
    assert Match.get("test1") is None
    assert Match.get("test2") is None

    res = MatchHistory.get("test1")
    assert len(res) == 1
    assert res[0].founder_id == "test1"
    assert res[0].waiter_id == "test2"
    assert res[0].founder_speech_count == 2
    assert res[0].waiter_speech_count == 1
    assert res[0].founder_used_points == 10
    assert res[0].waiter_used_points == 0
    assert res[0].waited_at == time
    assert res[0].ended_by == "test1"
    assert res[0].started_at > time
Beispiel #3
0
def test_on_match_increment_speech(mocker, monkeypatch):
    fix_matcher_rand(mocker)
    delegate = UserStateDelegate()
    user = User.get("test1")
    partner = User.get("test2")
    time = datetime.datetime.utcnow()
    record = MatchingQueue(created_at=time, finding_genders="male,female")
    uc, pc = [UserContext(u) for u in [user, partner]]

    delegate.on_found_partner(uc, pc, record)
    m1 = Match.get("test1")
    assert m1.founder_speech_count == 0
    assert m1.waiter_speech_count == 0

    delegate.on_speak(uc)
    assert m1.founder_speech_count == 1
    assert m1.waiter_speech_count == 0
    delegate.on_speak(uc)
    assert m1.founder_speech_count == 2
    assert m1.waiter_speech_count == 0

    delegate.on_speak(pc)
    assert m1.founder_speech_count == 2
    assert m1.waiter_speech_count == 1
    delegate.on_speak(pc)
    assert m1.founder_speech_count == 2
    assert m1.waiter_speech_count == 2
Beispiel #4
0
def main(args):
    text = "A lot of people are using Chatty.\n" \
           "Let's talk with them!"
    if args.test_to is None:
        from chatty.domain.model import match, notification
        now = datetime.datetime.utcnow()
        session = Session()
        for u in match.User.inactive_user(now, args.limit, args.gender):
            if u.locale != args.locale:
                continue
            print "candidate", u.id
            uc = UserContext(u)
            if not notification.Notification.notified_thesedays(now, u.id):
                try:
                    uc.send_btn(uc._(text),
                                [uc.langb(), uc.new_chat()], "NOTIFICATION1")
                except Exception as e:
                    notification.Notification.create(
                        u.id, "A lot of people are using Chatty", False)
                    logger.error(e)
                else:
                    notification.Notification.create(
                        u.id, "A lot of people are using Chatty", True)
                time.sleep(2)
        session.commit()
        session.close()
    else:
        fb.send_data(fb.button_data(args.test_to, text, "NOTIFICATION"))
Beispiel #5
0
def set_settings(user_id, languages, finding_genders, current_latitude,
                 current_longitude, search_radius, location_enabled):
    user_c = UserContext.get(user_id)
    user = user_c.user
    user.languages = [Language.get(lang) for lang in languages]
    user.finding_genders = ",".join(finding_genders)
    user.current_latitude = current_latitude
    user.current_longitude = current_longitude
    user.search_radius = search_radius
    user.location_enabled = location_enabled
    user_c.send_message(user_c._("Changes saved."), action.CHANGED_LANGUAGE)
Beispiel #6
0
def logged_in_with_fb(uid, code, redirect_url):
    fb_user_id, token, user = _login_update(code, uid, redirect_url)
    user.signup_date = datetime.datetime.now()
    if user.fb_id is None:
        user.fb_id = fb_user_id
        user.fb_access_token = token
        uc = UserContext.get(uid)
        uc.send_message(
            uc._("Sign up completed! "
                 "Click the Settings button to set discovery settings."),
            action.IDLE__SIGN_UP_COMPLETED)
        uc.do_action({}, action.IDLE__ACTION_AFTER_SIGNUP)
Beispiel #7
0
def test_on_try_search_on_banned(mocker, monkeypatch):
    fix_matcher_rand(mocker)
    delegate = UserStateDelegate()
    uc = UserContext(User.create("test1", "male,female", "male", 30))
    us = uc.status
    from chatty.util import fb

    mocksend = MagicMock()
    monkeypatch.setattr(fb, "send_data", mocksend)
    black_list.ban_user("test1")
    assert not delegate.on_try_search(us)
    assert mocksend.call_count == 1
    assert_message_is(mocksend.call_args_list[0][0][0], "test1", "suspended")
Beispiel #8
0
def settings(uidenc):
    uid = uidcrypt.decryptuid(uidenc)
    settings = bot.get_settings(uid)
    languages = [Lang(code=k, name=v, checked=(k in settings['languages']))
                 for k, v in
                 filter(lambda (k1, v1): k1 in config.ENABLED_LANGUAGES,
                        bot.get_language())]
    languages.sort(key=lambda x: x.name)
    userc = UserContext.get(uid)
    return dict(settings=settings,
                languages=languages,
                buy_points_url=fb.PAYMENT_LOGIN_URL.format(
                    uid=uidenc,
                    state=tokener.gen_token(uid, tokener.NS_PAYMENT)),
                userc=userc)
Beispiel #9
0
def run_methods(message, payload):
    user_id = message.sender.id
    user_c = UserContext.get(user_id)
    if payload.startswith("PREREPORT-"):
        prereport_user(user_c, payload.split("-")[1])
        return
    if payload.startswith("REPORT-"):
        report_user(user_c, payload.split("-")[1])
        return
    {
        ACTION: user_c.do_action,
        SEARCH: user_c.do_search,
        START: user_c.do_start,
        CANCEL_SEARCH: user_c.cancel_search,
        END_CONVERSATION: user_c.end_conversation,
        END_CONVERSATION_AND_SEARCH: user_c.end_conversation_and_search,
        SHARE_PROFILE: user_c.share_profile,
        SHARE_PROFILE_PRE: user_c.share_profile_pre,
    }.get(payload, user_c.do_unknown)(message)
Beispiel #10
0
def test_on_found_partner(mocker, monkeypatch):
    delegate = UserStateDelegate()
    fix_matcher_rand(mocker)

    user = User.create("test1",
                       finding_genders="male,female",
                       gender="male",
                       points=30)
    partner = User.create("test2",
                          finding_genders="male,female",
                          gender="male",
                          points=30)
    uc, pc = [UserContext(u) for u in [user, partner]]
    record = MatchingQueue(created_at=datetime.datetime.utcnow(),
                           finding_genders="male,female")
    delegate.on_found_partner(uc, pc, record)
    assert user.points == 30
    assert partner.points == 30
    assert Match.get("test1").founder_used_points == 0
    delegate.on_match_ended(uc, pc)

    user.finding_genders = "female"
    partner.gender = "female"
    delegate.on_found_partner(uc, pc, record)
    assert user.points == 20
    assert partner.points == 30
    assert Match.get("test1").founder_used_points == 10
    assert Match.get("test1").waiter_used_points == 0
    delegate.on_match_ended(uc, pc)

    delegate.on_found_partner(pc, uc, record)
    assert user.points == 20
    assert partner.points == 30
    record.finding_genders = "female"
    delegate.on_match_ended(uc, pc)

    delegate.on_found_partner(pc, uc, record)
    assert user.points == 10
    assert partner.points == 30
    assert Match.get("test1").founder_used_points == 0
    assert Match.get("test1").waiter_used_points == 10
Beispiel #11
0
def test_on_try_search(mocker, monkeypatch):
    fix_matcher_rand(mocker)
    delegate = UserStateDelegate()
    uc = UserContext(User.create("test1", "male,female", "male", 30))
    us = uc.status
    from chatty.util import fb

    mocksend = MagicMock()
    monkeypatch.setattr(fb, "send_data", mocksend)
    assert delegate.on_try_search(us)
    assert mocksend.call_count == 0

    us.user.points = 0
    assert delegate.on_try_search(us)
    assert mocksend.call_count == 0

    us.user.finding_genders = "female"
    assert not delegate.on_try_search(us)
    assert mocksend.call_count == 1

    assert_button(mocksend.call_args_list[0][0][0], "test1", "enough points",
                  [fb.web_button("", "/buy_points", "", "")])
Beispiel #12
0
def received_message(message):
    user_id = message.sender.id
    user_c = UserContext.get(user_id)
    if "text" in message.message._fields:
        t = message.message.text
        if t == "system-reset-lastmatched":
            reset_last_matched(user_id)
            return
        if t == "system-reset-fb-id":
            reset_fb_id(user_id)
            return
        if t == "system-index-page":
            send_index_page_test(user_c)
            return
        if t == "system-login-page":
            send_login_page(user_c)
            return
        if t == "system-buy-button-page":
            send_purchase_button_page(user_c)
            return
        if t == "system-reset-gender":
            reset_gender(user_id)
            return
    user_c.do_message(message)
Beispiel #13
0
def test_state_transition(mocker, monkeypatch):
    """状態遷移のテスト"""
    fix_matcher_rand(mocker)

    from chatty.domain.user_state import (
        User,
        IdleUserState,
        SearchingUserState,
        TalkingUserState,
    )
    from chatty.domain.model.match import Language

    import requests
    mock_request(monkeypatch, requests)
    # session
    session = model.Session()

    # ユーザーの言語設定を行う
    english = (session.query(Language).get('en_US')
               or Language(id='en_US', name='English'))
    user1 = User('TEST-01')
    user1.languages = [english]
    user2 = User('TEST-02', 'TEST-02')
    user2.languages = [english]
    user3 = User('TEST-03', 'TEST-03')
    user3.languages = [english]

    session.add(user1)
    session.add(user2)
    session.commit()
    user1_c = UserContext(user1)
    user2_c = UserContext(user2)
    user3_c = UserContext(user3)
    # At first, must be NoSignUpIdle
    assert isinstance(user1_c.status, NoSignUpIdleUserState)
    user1.fb_id = "1234"
    assert isinstance(user1_c.status, IdleUserState)
    # ユーザをサーチ状態にする
    user1_c.do_search(None)
    session.commit()
    assert isinstance(user1_c.status, SearchingUserState)

    # ユーザーを会話状態にする
    user2_c.do_search(None)
    session.commit()
    assert isinstance(user1_c.status, TalkingUserState)
    assert isinstance(user2_c.status, TalkingUserState)

    # 会話を終了する
    user2_c.end_conversation_and_search(None)
    session.commit()
    assert isinstance(user1_c.status, IdleUserState)
    assert isinstance(user2_c.status, SearchingUserState)

    # not match same tuple
    user1_c.do_search(None)
    session.commit()
    assert isinstance(user1_c.status, SearchingUserState)
    assert isinstance(user2_c.status, SearchingUserState)

    # match with pother partners.
    user3_c.do_search(None)
    session.commit()
    assert isinstance(user1_c.status, SearchingUserState)
    assert isinstance(user2_c.status, TalkingUserState)
    assert isinstance(user3_c.status, TalkingUserState)

    # 会話を終了する
    user2_c.end_conversation(None)
    session.commit()
    assert isinstance(user1_c.status, SearchingUserState)
    assert isinstance(user2_c.status, IdleUserState)
    assert isinstance(user3_c.status, IdleUserState)

    user1_c.cancel_search(None)
    session.commit()
    assert isinstance(user1_c.status, IdleUserState)
Beispiel #14
0
def pay_from_form(puid, token, points, price, currency):
    if not MenuPrice.is_valid(points, price, currency):
        abort(
            400,
            "Payment failed due to expiration of token. Please refresh your web browser and then try again."
        )
    astr = "{} {} {} {}".format(puid, token, points, price, currency)

    def translate(text):
        return uc._(text) if uc is not None else text

    try:
        user = User.get(puid)
        uc = UserContext(user)
        if user.points + points > 4000:
            abort(400, MESSAGE_TOO_MATCH_POINTS)
        customer = stripe.Customer.create(source=token,
                                          metadata={
                                              'puid': puid,
                                              'fb_id': user.fb_id
                                          })
        PaymentSource.create(user.fb_id, customer.id)
        charge = stripe.Charge.create(
            amount=price,
            currency=currency.lower(),
            description="Chatty: {} points".format(points),
            customer=customer.id,
            metadata={
                'puid': puid,
                'fb_id': user.fb_id
            })
        user.points += int(points)
        Payment.create(charge.id, user.fb_id, customer.id, points, price,
                       currency.lower())
        # https://stripe.com/docs/api#error_handling
        # https://stripe.com/docs/declines#decline-codes

    except stripe.error.CardError as e:
        # Since it's a decline, stripe.error.CardError will be caught
        logger.error("Failed payment {} {} ".format(astr, e.json_body))
        abort(400, translate(MESSAGE_CONTACT_CREDIT))
    except stripe.error.RateLimitError as e:
        # Too many requests made to the API too quickly
        abort(400, translate(MESSAGE_CONTACT_US))
    except stripe.error.InvalidRequestError as e:
        # Invalid parameters were supplied to Stripe's API
        slack.post("Failed payment {} {}".format(astr, e.json_body))
        abort(400, translate(MESSAGE_CONTACT_US))
    except stripe.error.AuthenticationError as e:
        slack.post("Failed payment {} {}".format(astr, e.json_body))
        abort(400, translate(MESSAGE_CONTACT_US))
    except stripe.error.APIConnectionError as e:
        # Network communication with Stripe failed
        abort(400, translate(MESSAGE_CONTACT_US))
    except stripe.error.StripeError as e:
        slack.post("Failed payment {} {}".format(astr, e.json_body))
        # Display a very generic error to the user, and maybe send
        # yourself an email
        abort(400, translate(MESSAGE_CONTACT_US))
    except HTTPError as e:
        raise e
    except Exception as e:
        slack.post("Failed payment {} {}".format(astr, e.message))
        # Something else happened, completely unrelated to Stripe
        abort(400, translate(MESSAGE_CONTACT_US))
    return user.points
Beispiel #15
0
def translate(uid, text):
    return UserContext.get(uid)._(text)
Beispiel #16
0
def do_action(uid):
    if not User.exists(uid):
        return
    UserContext.get(uid).do_action({})
Beispiel #17
0
def test_user_state_check_error(mocker, monkeypatch, caplog):
    fix_matcher_rand(mocker)
    from chatty.domain.user_state import (
        User,
        IdleUserState,
        SearchingUserState,
        TalkingUserState,
    )
    from chatty.domain.model.match import Language

    import requests
    from chatty.util.fb import requests as fbreq
    mock_request(monkeypatch, requests)
    mock_request(monkeypatch, fbreq)

    # session
    session = model.Session()

    # ユーザーの言語設定を行う
    english = (session.query(Language).get('en_US')
               or Language(id='en_US', name='English'))
    user = User('TEST-01', 'TEST-01')
    user.languages = [english]
    partner = User('TEST-02', 'TEST-02')
    partner.languages = [english]

    session.add(user)
    session.add(partner)
    session.commit()
    user_c = UserContext(user)
    partner_c = UserContext(partner)
    # logging 設定
    caplog.set_level(logging.INFO)

    # エラーが返ってきた場合ワーニングログを出力
    mock_request(monkeypatch, fbreq,
                 {"error": {
                     "code": 190,
                     "error_subcode": 1234567,
                 }})
    user_c.status.send_message('message', action.IDLE__MESSAGE)
    # warning log が出力されているはず
    for rec in caplog.records:
        print('log: ', rec)
        if (rec.levelname == 'WARNING'
                and rec.message.startswith('Facebook send api error:')):
            break
    else:
        assert False, 'Not found error message'

    session.commit()

    # メッセージ送信先がメッセージを受信できない場合は検索,会話状態から削除する

    # 検索状態へ
    normalres = {
        'message_id': 'mid.1484759787552:e29cca0c16',
        'recipient_id': '1261793003907488'
    }
    mock_request(monkeypatch, fbreq, normalres)
    user_c.do_search(None)
    session.commit()
    assert isinstance(user_c.status, SearchingUserState)

    mock_request(
        monkeypatch,
        fbreq,
        {"error": {
            "code": 10,
            "error_subcode": 2018108,
        }},
    )
    user_c.status.send_message('message', action.SEARCHING__MESSAGE)
    session.commit()

    # アイドル状態になっているはず
    assert isinstance(user_c.status, IdleUserState)

    # 会話状態へ
    mock_request(monkeypatch, fbreq, normalres)
    user_c.do_search(None)
    partner_c.do_search(None)
    session.commit()

    assert isinstance(user_c.status, TalkingUserState)
    assert isinstance(partner_c.status, TalkingUserState)

    def m(url, json):
        recipient_ = json['recipient']['id']
        if recipient_ == "TEST-01":
            return MagicMock(json=MagicMock(return_value=normalres))
        elif recipient_ == "TEST-02":
            return MagicMock(json=MagicMock(
                return_value={
                    "error": {
                        "code": 200,
                        "error_subcode": 1545041,
                    }
                }))
        raise ValueError(
            "dummy recipient must be TEST-01 or TEST-02 but {}".format(
                recipient_))

    monkeypatch.setattr(fbreq, 'post', m)
    user_c.status.do_message(
        MagicMock(message=MagicMock(text="hello", _fields=["text"])))
    session.commit()

    # アイドル状態になっているはず
    assert isinstance(user_c.status, IdleUserState)
    assert isinstance(partner_c.status, IdleUserState)