def testResult(self): test_id = 'test' watches = [] now_utc = utc_now() + timedelta(days=-1) for i in range(WATCH_COUNTS): watches.append( Watch(date=now_utc + timedelta(seconds=WATCH_INTERVAL * (i + 1)), sent_count=1, is_replied=True)) drinking = Drinking(id=test_id, mid=test_id, start_date=now_utc, is_done=True, watches=watches) drinking.put() check_result() (status, info) = get_status(test_id) self.assertEqual(status, User.STAT_WAIT_RESULT) result = u'二日酔い' msg = handle_result(result, info) drinking = Drinking.get_key(test_id).get() self.assertEqual(drinking.result, result, drinking.result) self.assertEqual(drinking.sentiment, 0.0) self.assertEqual(drinking.magnitude, 0.0) self.assertTrue(msg.find(u'次回も大人飲み') >= 0, msg)
def testWatchFinished(self): TEST_INTERVAL = 5 test_id = 'test' watches = [] now_utc = utc_now() + timedelta(seconds=TEST_INTERVAL) for i in range(WATCH_COUNTS): watches.append( Watch(date=now_utc + timedelta(seconds=TEST_INTERVAL * (i + 1)))) drinking = Drinking(id=test_id, mid=test_id, start_date=now_utc, watches=watches) drinking.put() sleep(TEST_INTERVAL * 2 + 2) watch_drinkings() (stat, info) = get_status(test_id, is_peek=True) msg = handle_reply(u'帰宅した', info) self.assertTrue(msg.startswith(u'お疲れさまでした'), msg) drinking = Drinking.get_key(test_id).get() self.assertEqual(drinking.finished_date.year, now_utc.year) self.assertEqual(drinking.finished_date.month, now_utc.month) self.assertEqual(drinking.finished_date.day, now_utc.day) self.assertEqual(drinking.finished_date.hour, now_utc.hour) for j, watch in enumerate(drinking.watches): self.assertEqual(watch.is_replied, True if j == 0 else False) self.assertEqual(watch.sent_count, 1 if j == 0 else 0) self.assertTrue(drinking.is_done)
def testWatchDelayed(self): TEST_INTERVAL = 5 test_id = 'test' watches = [] now_utc = utc_now() + timedelta(seconds=TEST_INTERVAL) for i in range(WATCH_COUNTS): watches.append( Watch(date=now_utc + timedelta(seconds=TEST_INTERVAL * (i + 1)))) drinking = Drinking(id=test_id, mid=test_id, start_date=now_utc, watches=watches) drinking.put() sleep(TEST_INTERVAL * 2 + 2) for i in range(5): watch_drinkings() (status, info) = get_status(test_id, True) self.assertEqual(status, User.STAT_WAIT_REPLY) self.assertTrue(info is not None) self.assertEqual(info['key'], test_id, info['key']) self.assertEqual(info['idx'], 0) drinking = Drinking.get_key(test_id).get() for j, watch in enumerate(drinking.watches): self.assertEqual(watch.is_replied, False) self.assertEqual(watch.sent_count, i + 1 if j == 0 else 0) drinking = Drinking.get_key(test_id).get() self.assertFalse(drinking.is_done)
def testWatch(self): TEST_INTERVAL = 10 test_id = 'test' watches = [] now_utc = utc_now() + timedelta(seconds=TEST_INTERVAL) for i in range(WATCH_COUNTS): watches.append( Watch(date=now_utc + timedelta(seconds=TEST_INTERVAL * (i + 1)))) drinking = Drinking(id=test_id, mid=test_id, start_date=now_utc, watches=watches) drinking.put() sleep(TEST_INTERVAL + 2) for i in range(WATCH_COUNTS): sleep(TEST_INTERVAL) watch_drinkings() (status, info) = get_status(test_id, is_peek=True) self.assertEqual(status, User.STAT_WAIT_REPLY) self.assertTrue(info is not None) self.assertEqual(info['key'], test_id, info['key']) self.assertEqual(info['idx'], i, info['idx']) drinking = Drinking.get_key(test_id).get() for j, watch in enumerate(drinking.watches): self.assertEqual(watch.is_replied, True if j < i else False) self.assertEqual(watch.sent_count, 1 if j <= i else 0) self.assertFalse(drinking.is_done) content = { "events": [{ "replyToken": "xxxx", "type": "message", "source": { "type": "user", "userId": test_id }, "message": { "type": "text", "text": "OK" } }] } recv_req = WebhookRequest(json.dumps(content)) receive_message(recv_req) (status, info) = get_status(test_id) self.assertEqual(status, User.STAT_NONE) drinking = Drinking.get_key(test_id).get() for j, watch in enumerate(drinking.watches): self.assertEqual(watch.is_replied, True if j <= i else False) self.assertEqual(watch.sent_count, 1 if j <= i else 0) drinking = Drinking.get_key(test_id).get() self.assertFalse(drinking.is_done)
def testHistory(self): test_id = 'test' test_msgs = [u'過去の飲みは?', u'これまでの呑みを', u'今までの呑みは?', u'前の呑み'] for test_msg in test_msgs: msg = handle_message(test_id, test_msg) self.assertTrue(msg.startswith(u'まだ飲みの'), msg) user = User(id=test_id) user.put() for test_msg in test_msgs: msg = handle_message(test_id, test_msg) self.assertTrue(msg.startswith(u'過去の飲みは'), msg) user = User.get_key(test_id).get() self.assertTrue(user.history_url != None and len(user.history_url) > 0) self.assertTrue(user.history_expire < utc_now() + timedelta(minutes=HISTORY_DURATION)) sdt = utc_now() + timedelta(days=-2) check_sdt = [] for i in range(MAX_HISTORY + 1): watches = [] for j in range(WATCH_COUNTS): watches.append( Watch(date=sdt + timedelta(minutes=WATCH_INTERVAL * (i + 1)))) key = test_id + sdt.strftime('%Y%m%d%H%M') drinking = Drinking(id=key, mid=test_id, start_date=sdt, watches=watches) drinking.put() check_sdt.append( format_jdate(sdt.replace(tzinfo=tz_utc).astimezone(tz_jst))) sdt = sdt + timedelta(days=-1) self.assertEqual(get_drinking_history_content(user.history_url[:-1]), None) soup = BeautifulSoup(get_drinking_history_content(user.history_url), 'html.parser') trs = soup.body.div.table.tbody.findAll('tr') self.assertEqual(len(trs), MAX_HISTORY * 2) for i in range(MAX_HISTORY): self.assertEqual(trs[i * 2].td.text, check_sdt[i])
def handle_message(user_id, msg): mid = user_id (elms, drink_id, cancel_id, finished_id, history_id) = parse_message(msg) if history_id >= 0 and drink_id >= 0 and depends_drink( history_id, elms, drink_id): # this is request for drinking history return history_drinking(mid) if finished_id >= 0: # this is finish message return finish_drinking(mid) if cancel_id >= 0: # this is cancel message return cancel_drinking(mid) if drink_id == -1: # this is not nomi message... return None # user can have only one drink if has_drinking(mid): return u'飲みは1つしか予約できません。予約した飲みをキャンセルするには「やめ」とメッセージしてください。' # 3rd, determine date and time now = utc_now().replace(second=0, microsecond=0) s_date = datetime.now(tz=tz_jst).replace(second=0, microsecond=0) for id, elm in elms.items(): if depends_drink(id, elms, drink_id): start_info = '' for morphem in elm['morphemlist']: start_info += morphem['surface'] # find time time_patterns = [ u'(\d\d)[時じ::](\d\d)\D', '(\d\d)(\d\d)', u'(\d+)[時じ::](\d+)', u'(\d+)[時じ]' ] for pattern in time_patterns: mo = re.search(pattern, start_info) if mo: hour = int(mo.group(1)) minute = int(mo.group(2)) if mo.lastindex == 2 else 0 if hour < 12 and \ (start_info.find('PM') >= 0 or start_info.find('pm') >= 0 or start_info.find(u'午後') >= 0 or start_info.find(u'ごご') >= 0): hour += 12 s_date = s_date.replace(hour=hour, minute=minute) break # find date if start_info.find(u'明日') >= 0 or \ start_info.find(u'あした') >= 0 or \ start_info.find(u'あす') >= 0: s_date = s_date + timedelta(days=1) elif start_info.find(u'明後日') >= 0 or \ start_info.find(u'あさって') >= 0: s_date = s_date + timedelta(days=2) else: date_patterns = [u'(\d+)月(\d+)', '(\d+)/(\d+)'] for pattern in date_patterns: mo = re.search(pattern, start_info) if mo: month = int(mo.group(1)) day = int(mo.group(2)) s_date = s_date.replace(month=month, day=day) break # store data watches = [] utc_s_date = s_date.astimezone(tz_utc).replace(tzinfo=None) s_date_str = u'%d月%d日%d時%d分' % (s_date.month, s_date.day, s_date.hour, s_date.minute) # check if s_date is valid if utc_s_date < now: # past date !! return s_date_str + u'は過去です。' # check duplicate key = mid + s_date.strftime('%Y%m%d%H%M') if is_duplicated_drinking(key): return s_date_str + u'からの飲みは登録済みです。' for i in range(WATCH_COUNTS): watches.append( Watch(date=utc_s_date + timedelta(minutes=WATCH_INTERVAL * (i + 1)))) drinking = Drinking(id=key, mid=mid, start_date=utc_s_date, watches=watches) drinking.put() msg = s_date_str + u'から飲むのですね!\n約%d分毎に%d回メッセージを送信しますので、何を何杯飲んだかなど、状況を返信してくださいね。帰宅したら帰宅とメッセージしてください。' % ( WATCH_INTERVAL, WATCH_COUNTS) # past drinkings query = Drinking.query( Drinking.mid == mid, Drinking.is_done == True).order(-Drinking.start_date) prev_drinkings = query.fetch(1) if len(prev_drinkings): prev_drinking = prev_drinkings[0] msg += u'\n\nちなみに前回の飲みは%sで、その時は%s\n' % (format_jdate( prev_drinking.start_date.replace( tzinfo=tz_utc).astimezone(tz_jst)), get_drinking_quality_word( prev_drinking.sentiment, prev_drinking.magnitude)) sep = u'' for kind in prev_drinking.summary: msg += sep + u' %s %d 杯' % (kind, prev_drinking.summary[kind]) sep = u'\n' return msg