def testSendMessagesDisabled(self): # Testing that message for disabled user is not sent # But rescheduled to next day Twitter = TwitterMockup() today = datetime.date.today() self.createUser("da_zbur","disabled",10) d1 = self.createDictEntry("da_zbur",2,"lucrative",\ u"profitable, moneymaking, remunerative","[LOO-kruh-tiv]") current_time = int(time.time()) l1 = self.createLearnListItem("da_zbur",d1,today, current_time) messages_generator = sendMessagesGenerator(Twitter, logging) m_list = [] while True: try: message = messages_generator.next() except StopIteration: break m_list.append(message) # Testing that LearnListItem was rescheduled properly ll = LearnList.all().fetch(1)[0] self.assertEqual(1, ll.total_served) self.assertEqual(today + datetime.timedelta(days=1), ll.next_serve_date) self.assertEqual([None], m_list) self.assertEqual(sys.maxint, ll.next_serve_time)
def prepareEmailMessagesGenerator(): # This must be run after buildDailyList # Since only there a daily message limit is applied # though, this limit can be different for emails path_current = os.path.dirname(__file__) root_path = os.path.split(path_current)[0] view_path = root_path + "/views/daily_email.html" today = datetime.date.today() emails_dict = {} for user in User.all().filter("account_status =", "enabled").\ filter("use_daily_email =", "yes"): parameters = {} parameters["dict_row"] = [] for lli in LearnList.all().\ filter("next_serve_date =", today).\ filter("twitter_user ="******" " + lli.dict_entry.pronounce) l.append(lli.dict_entry.meaning) parameters["dict_row"].append(l) emails_dict["email"] = user.email emails_dict["message"] = template.\ render(view_path, parameters) yield emails_dict
def testDeleteDictEntry(self): today = datetime.date.today() current_time = int(time.time()) u = self.createUser("da_zbur", "enabled", 10) u.use_questions = "yes" u.put() d1 = self.createDictEntry("da_zbur", 2, "lucrative", \ u"profitable, moneymaking, remunerative", "[LOO-kruh-tiv]") d2 = self.createDictEntry("da_zbur", 2, "ferociously(en)", \ u"жестоко, яростно, свирепо, дико, неистово. Ужасно, невыносимо.") l1 = self.createLearnListItem("da_zbur", d1, today, current_time) l2 = self.createLearnListItem("da_zbur", d2, today, current_time) self.createQuestion(l1, today, "da_zbur", d1.word, "profitable, moneymaking", 1, today, 100) self.createQuestion(l2, today, "da_zbur", d2.word, u"лажа", 2, today, 0) deleteDictEntry(u, "lucrative[LOO-kruh-tiv]") self.assertEqual(None, Dictionary.all().\ filter("word =", "lucrative").get()) self.assertEqual(1, LearnList.all().count()) self.assertEqual(1, Question.all().count()) self.assertEqual(1, Dictionary.all().count())
def createLearnListItem(self, twitter_user, dict_entry,\ next_serve_date, next_serve_time=0): learnListItem = LearnList() learnListItem.twitter_user = twitter_user learnListItem.dict_entry = dict_entry learnListItem.next_serve_date = next_serve_date learnListItem.next_serve_time = next_serve_time learnListItem.total_served = 1 learnListItem.put() return learnListItem
def sendMessagesGenerator(TwitterAPI, logging): current_time = int(time.time()) # Are there messages to send out in next SCHEDULERUN seconds? next_planned_interval = current_time + SCHEDULERUN today = datetime.date.today() for lli in LearnList.all().\ filter("next_serve_time <=", next_planned_interval): result = None # Don't send messages if user is disabled user = User.all().filter("twitter =", lli.twitter_user).\ filter("account_status =", "enabled").fetch(1) if user == []: yield result # If user has messages in todays list but is disabled now # Let's just reschedule it to tomorrow lli.next_serve_date = addDays(lli.next_serve_date, 1) lli.next_serve_time = sys.maxint lli.put() continue # If there is a question to send, prepare a different # Twitter message format question = Question.all().filter("lli_ref =", lli).\ filter("answer_received =", None).fetch(1) if question != []: message = prepareQuestionMessage(lli) else: message = prepareTwitterMessage(lli) try: #status = TwitterAPI.api.PostUpdate(message) status = TwitterAPI.api.PostDirectMessage(lli.twitter_user,\ message) result = message # For questions we do no recalculate new interval right away # We do it when answer is recieved or no received # Instead we update Question entity if question == []: answer_rating = lli.latest_answer_rating rescheduleLearnListItem(lli, answer_rating) else: question[0].question_sent = today question[0].question_message_id = status.id question[0].put() # We also need to make sure this message is not sent again automatically # Until answer is recieved or it expires lli.next_serve_time = sys.maxint lli.put() except TwitterError: print TwitterError.message logging.error("Twitter error when sending message %s" % message) yield result
def getParameters(user): parameters = {} parameters["dict_row"] = [] parameters["username"] = user.username for lli in LearnList.all().filter("twitter_user ="******"next_serve_date").run(): l = [] l.append(lli.dict_entry.word+" "+lli.dict_entry.pronounce) l.append(lli.dict_entry.meaning) l.append(lli.next_serve_date.strftime("%B %d")) parameters["dict_row"].append(l) return parameters
def deleteDictEntry(user, word): word, _ = parseOpt(word) dict_entry = Dictionary.all().\ filter("twitter_user ="******"word =", word.strip()).get() if dict_entry: lli = LearnList.all().\ filter("dict_entry =", dict_entry.key()).get() for q in Question.all().filter("lli_ref =", lli.key()).run(): q.delete() lli.delete() dict_entry.delete() return json.dumps({})
def testProcessMessageFromNonExistentUser(self): # Message from user "spammer" who doesn't exist in database # It must not be processed and must not be saved json_file = open("files/direct_message_spammer.json") message_json = simplejson.load(json_file) twitter_dm = DirectMessage.NewFromJsonDict(message_json) processMessage(twitter_dm) query = Dictionary.all() results = query.fetch(1) self.assertEqual(0, len(results)) self.assertEqual("spammer", twitter_dm.sender_screen_name) # Test integration with LearnList query = LearnList.all() ll_results = query.fetch(2) self.assertEqual(0, len(ll_results))
def buildDailyList(day, logging): logging.debug("Entered Build Daily List") current_timestamp = int(time.time()) for user in User.all().filter("account_status =", "enabled"): llQuery = LearnList.all().filter("twitter_user ="******"next_serve_date =", day) use_questions = user.use_questions utc_offset = 0 if user.utc_offset != None: utc_offset = user.utc_offset i = 0 message_list = [] for learnListItem in llQuery.run(): # If we are within limit of messages per dat, keep adding if i < user.messages_per_day: message_list.append(learnListItem) i = i + 1 # if we exceeded limit per day, reschedule to next day else: learnListItem.next_serve_date =\ addDays(learnListItem.next_serve_date, 1) learnListItem.put() i = i + 1 # Set next run timestamp for words scheduled for today interval_gen = getNextRunInterval(len(message_list)) for l in message_list: try: time_shift = FIRSTMESSAGEHOUR * 3600 - utc_offset * 3600 s = interval_gen.next() l.next_serve_time = current_timestamp + s + time_shift # Create new question entry for every second serve # If user has this option enabled if use_questions == "yes" and (l.total_served % 2 == 0): q = Question() q.lli_ref = l q.twitter_user = user.twitter q.word = l.dict_entry.word q.put() l.put() except StopIteration: pass
def testAddNewLearnListItem(self): # Preparing datastore by prepopulating some data user = User() user.username = "******" user.twitter = "ny_blin" user.total_points = 0 user.put() json_file = open("files/direct_message2.json") message_json = simplejson.load(json_file) twitter_dm = DirectMessage.NewFromJsonDict(message_json) processMessage(twitter_dm) query = LearnList.all().filter('twitter_user ='******'ny_blin') results = query.fetch(2) self.assertEqual(1, len(results)) self.assertEqual('ny_blin', results[0].twitter_user) self.assertEqual(2.5, results[0].interval_days) self.assertEqual(1.5, results[0].efactor) self.assertEqual(1, results[0].total_served) now_plus_two = datetime.date.today() +\ datetime.timedelta(days=2) self.assertEqual(now_plus_two, results[0].next_serve_date)
def testProcessMessageNormalAddForExistingUser(self): json_file = open("files/direct_message1.json") message_json = simplejson.load(json_file) twitter_dm = DirectMessage.NewFromJsonDict(message_json) processMessage(twitter_dm) query = Dictionary.all() results = query.fetch(1) self.assertEqual(1, len(results)) self.assertEqual("", results[0].pronounce) self.assertEqual("da_zbur", results[0].twitter_user) self.assertEqual(289180663729512448L, results[0].message_id) self.assertEqual("to advet", results[0].word) self.assertEqual(u"обращаться к,ссылаться на",\ results[0].meaning) self.assertEqual(0, results[0].served) self.assertEqual(None, results[0].source_lang) self.assertEqual(1, User.all().filter("twitter =",\ "da_zbur").get().total_points) # Test integration with LearnList query = LearnList.all() ll_results = query.fetch(2) self.assertEqual(1, len(ll_results)) # Check if LearnList references same object self.assertEqual(ll_results[0].dict_entry.key(), results[0].key())
def addNewLearnListItem(twitter_user, dict_entry): l = LearnList() now = datetime.date.today() i = getNextInterval(1, 0, 0, 1) l.twitter_user = twitter_user l.dict_entry = dict_entry l.interval_days = i['new_interval'] l.next_serve_date = addDays(now, int(l.interval_days)) l.efactor = i['new_efactor'] l.next_serve_time = sys.maxint l.total_served = 1 l.latest_answer_rating = 0 l.put()
def testBuildDailyList(self): # Prepare 4 users: 3 active one disabled, one with # limit of messages per day self.createUser("ny_blin","enabled",10) u = self.createUser("da_zbur","enabled",10) # Change timezone for da_zbur u.utc_offset = -5 u.put() self.createUser("mr_qizz","disabled",10) self.createUser("mr_2_per_day","enabled",2) d1 = self.createDictEntry("ny_blin",1,"cat",u"котик") d2 = self.createDictEntry("da_zbur",2,"dog",u"собачка") d3 = self.createDictEntry("da_zbur",3,"heron",u"цапля") d4 = self.createDictEntry("mr_qizz",4,"raccoon",u"енотик") today = datetime.date.today() tomorrow = today + datetime.timedelta(days=1) current_timestamp = int(time.time()) self.createLearnListItem("ny_blin",d1,today) self.createLearnListItem("da_zbur",d2,today) self.createLearnListItem("da_zbur",d3,today) self.createLearnListItem("da_zbur",d4,tomorrow) self.createLearnListItem("mr_qizz",d4,today) self.createLearnListItem("mr_2_per_day",d1,today) self.createLearnListItem("mr_2_per_day",d2,today) self.createLearnListItem("mr_2_per_day",d3,today) self.createLearnListItem("mr_2_per_day",d4,today) buildDailyList(today, logging) dailyList = [] for i in LearnList.all().filter("next_serve_date =",today).run(): dailyList.append(i) self.assertEqual(6, len(dailyList)) self.assertEqual("ny_blin", dailyList[0].twitter_user) self.assertEqual(d1.key(), dailyList[0].dict_entry.key()) self.assertNotEqual(0, dailyList[0].next_serve_time) self.assertTrue(current_timestamp < dailyList[0].next_serve_time) self.assertEqual("da_zbur", dailyList[1].twitter_user) self.assertEqual(d2.key(), dailyList[1].dict_entry.key()) self.assertNotEqual(0, dailyList[1].next_serve_time) self.assertEqual("da_zbur", dailyList[2].twitter_user) self.assertEqual(d3.key(), dailyList[2].dict_entry.key()) self.assertNotEqual(0, dailyList[2].next_serve_time) self.assertEqual("mr_qizz", dailyList[3].twitter_user) self.assertEqual(0, dailyList[3].next_serve_time) self.assertEqual("mr_2_per_day", dailyList[4].twitter_user) self.assertEqual(d1.key(), dailyList[4].dict_entry.key()) self.assertNotEqual(0, dailyList[4].next_serve_time) self.assertEqual("mr_2_per_day", dailyList[5].twitter_user) self.assertEqual(d2.key(), dailyList[5].dict_entry.key()) self.assertNotEqual(0, dailyList[5].next_serve_time) # Now let's check if 2 messages for mr_2_per day got rescheduled # for tomorrow. Plus there is a message for da_zbur scheduled for # tomorrow as well buildDailyList(tomorrow, logging) dailyList = [] for i in LearnList.all().filter("next_serve_date =",tomorrow).run(): dailyList.append(i) self.assertEqual(3, len(dailyList)) self.assertEqual("da_zbur", dailyList[0].twitter_user) self.assertEqual(d4.key(), dailyList[0].dict_entry.key()) self.assertNotEqual(0, dailyList[0].next_serve_time) self.assertEqual("mr_2_per_day", dailyList[1].twitter_user) self.assertEqual(d3.key(), dailyList[1].dict_entry.key()) self.assertNotEqual(0, dailyList[1].next_serve_time) self.assertEqual("mr_2_per_day", dailyList[2].twitter_user) self.assertEqual(d4.key(), dailyList[2].dict_entry.key()) self.assertNotEqual(0, dailyList[2].next_serve_time) # Finally let's check that building tomorrow's list didn't screw up # the today's list dailyList = [] for i in LearnList.all().filter("next_serve_date =",today).run(): dailyList.append(i) self.assertEqual(6, len(dailyList))