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") == "دردشة جديدة"
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
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
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"))
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)
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)
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")
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)
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)
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
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", "", "")])
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)
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)
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
def translate(uid, text): return UserContext.get(uid)._(text)
def do_action(uid): if not User.exists(uid): return UserContext.get(uid).do_action({})
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)