def exportDatabase(): rlSQL = RobertLogMSSQL(host=config.db_server,user=config.db_user,pwd=config.db_pwd,db="robertlog") with open("rawmsg.csv", 'w', encoding='utf-8') as csvout: fRawMsg = csv.writer(csvout, delimiter='\t', quotechar='"') rlSQL.DumpTableToStream("RawMsg", fRawMsg) with open("actions.csv", 'w', encoding='utf-8') as csvout: fActions = csv.writer(csvout, delimiter='\t', quotechar='"') rlSQL.DumpTableToStream("Actions", fActions)
def importDatabase(): rlSQL = RobertLogMSSQL(host=config.db_server,user=config.db_user,pwd=config.db_pwd,db="robertlog") with open("rawmsg.csv", 'r', encoding='utf-8') as cvsin: fRawMsg = csv.reader(cvsin, delimiter='\t', quotechar='"') rlSQL.ImportListToDB("RawMsg", "MsgID, TimeStamp, RawMsg, FromUser, ToUser, MsgType", fRawMsg) print(fRawMsg.line_num) with open("actions.csv", 'r', encoding='utf-8') as cvsin: fActions = csv.reader(cvsin, delimiter='\t', quotechar='"') rlSQL.ImportListToDB("Actions", "ActionID, CreateTime, ActionType, FromUser, ActionDetail, ActionStatus", fActions) print(fActions.line_num)
def get_dailyreport(num_days): reports = [] rlSQL = RobertLogMSSQL(host=config.db_server, user=config.db_user, pwd=config.db_pwd, db="robertlog") cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) actions = rlSQL.GetActionReports(20 * num_days) milk = 0 breast = 0 breastNum = 0 poop = 0 sleep = 0 daysShown = 0 for a in actions: if a.Status == Action.Deleted: continue if a.TimeStamp.day != cur.day and (milk != 0 or breast != 0): reports.append(DailyReport(milk_ml = milk, milk_min = breast,\ milk_num = breastNum, poop = poop, sleep = sleep, date = a.TimeStamp)) milk = 0 breast = 0 poop = 0 breastNum = 0 sleep = 0 daysShown += 1 cur = a.TimeStamp if a.Type == ActionType.Feed: nums = re.findall(r"\d+", a.Detail) if len(nums) > 0: d = int(nums[0]) if a.Detail.find("母乳") >= 0: breast += d breastNum += 1 elif a.Detail.find("奶瓶") >= 0: milk += d elif a.Type == ActionType.Poop: poop += 1 elif a.Type == ActionType.WakeUp: ect = extract_cn_time() sleep += ect.extract_time_delta(a.Detail) elif a.Type == ActionType.Notes: #response += "{0}日{1}\n".format(cur.strftime("%m-%d"),a.GenBrief()) pass return reports
class ActionCenter: #SQL rlSQL = RobertLogMSSQL(host=config.db_server,user=config.db_user,pwd=config.db_pwd,db="robertlog") #Action List FeedKeywords = {u"吃了",u"喂了", u"喂奶", u"吃奶", u"奶粉", u"喝奶"} ReportsKeywords = {u"报告", u"总结", u"情况"} WeeklyReportsKeywords = {u"一周报告", u"一周总结", u"一周情况", u"本周总结"} NotesKeywords = {u"备注", u"笔记"} mLKeywords = {u"ml",u"毫升"} MinKeywords = {u"分钟"} ADKeywords = {u"AD",u"ad"} PillsKeywords = {u"吃药",u"喂药" } PoopKeywords = {u"拉屎",u"大便", } BathKeywords = {u"洗澡"} RemoveKeywords = {u"撤销", u"删除"} FallSleepKeywords = {u"睡着"}#, u"睡觉"} WakeUpKeywords = {u"醒了", u"睡醒"} ListImageKeywords = {u"看照片"} ListSleepTimeKeywords = {u"几点睡",u"睡多久", u"睡了多久"} DebugMsgKeywords = {u"调试消息"} EatCaKeywords = {u"补钙", u"钙片"} ComFoodKeywords = [u"辅食", u"吃饭"] ComFoodListKeywords = {u"食谱"} FixInputKeywords = {u"补录"} PowderKeywords = {u"奶粉"} SnacksKeywords = [u"零食"] ViewNotesKeywords = {u"看随笔"} MMFoodLogKeywords = [u"妈妈饮食"] users_can_write = {"ocgSc0eChTDEABMBHJ_urv4lMeCE", "ocgSc0fzGH2Os2cmFYQ58zdDPCWw", \ "ocgSc0cpvPB5V7KPdcBSdu0VQvXQ", \ "ocgSc0X3el46D3JbN5Brwr0SVrII", \ "ocgSc0fIrUDX5iDolCX_D0KBYiGs", \ "ocgSc0a7I2-DcquxOaN5G43BOSbQ"} #stan, hanhan, huaiyan, zhangxin, lishu, luchun user_mapping = {"ocgSc0eChTDEABMBHJ_urv4lMeCE" : "李菡", \ "ocgSc0fzGH2Os2cmFYQ58zdDPCWw" : "孙磊", \ "ocgSc0cpvPB5V7KPdcBSdu0VQvXQ" : "奶奶", \ "ocgSc0X3el46D3JbN5Brwr0SVrII" : "姥姥", \ "ocgSc0fIrUDX5iDolCX_D0KBYiGs" : "老爷", \ "ocgSc0a7I2-DcquxOaN5G43BOSbQ" : "爷爷"} actiontype_skip_log = {ActionType.UnKnown, ActionType.Reports, ActionType.WeeklyReports,\ ActionType.Remove, ActionType.NoPermission, ActionType.ListImage, \ ActionType.SleepTime, ActionType.DebugMsg, ActionType.RemoveSpecific, \ ActionType.ErrStatus, ActionType.ComFoodList, ActionType.ViewNotes} def check_strList(self, str, listStr): for s in listStr: if str.find(s) >= 0 : return True return False def DetectAction(self, msg): msg.RawContent = msg.RawContent.replace(":", ":") action = Action(msg) num2d = num_cn2digital() ect = extract_cn_time() content = num2d.replace_cn_digital(msg.RawContent) t = ect.extract_time(content) if t is not None and len(t) > 0: action.TimeStamp = t[0] content = ect.remove_time(content) if self.check_strList(msg.RawContent, self.NotesKeywords): action.Type = ActionType.Notes action.Detail = msg.RawContent for k in self.NotesKeywords: action.Detail = action.Detail.lstrip(k) elif self.check_strList(msg.RawContent, self.ListSleepTimeKeywords): action.Type = ActionType.SleepTime self.get_latest_sleep(action, num2d, ect) elif self.check_strList(msg.RawContent, self.ADKeywords): action.Type = ActionType.AD elif self.check_strList(msg.RawContent, self.EatCaKeywords): action.Type = ActionType.EatCa elif self.check_strList(msg.RawContent, self.ComFoodListKeywords): action.Type = ActionType.ComFoodList elif self.check_strList(msg.RawContent, self.ComFoodKeywords): action.Type = ActionType.ComFood start = msg.RawContent.find(self.ComFoodKeywords[0]) if start < 0: start = msg.RawContent.find(self.ComFoodKeywords[1]) detail = msg.RawContent[start+2:].strip() action.Detail = detail elif self.check_strList(msg.RawContent, self.MMFoodLogKeywords): action.Type = ActionType.MMFoodLog start = msg.RawContent.find(self.MMFoodLogKeywords[0]) if start < 0: start = 0 detail = msg.RawContent[start+4:].strip() action.Detail = detail elif self.check_strList(msg.RawContent, self.SnacksKeywords): action.Type = ActionType.Snacks start = msg.RawContent.find(self.SnacksKeywords[0]) detail = msg.RawContent[start+2:].strip() action.Detail = detail elif self.check_strList(content, self.FeedKeywords): #feed action.Type = ActionType.Feed action.Status = Action.Active nums = re.findall(r"\d+",content) if len(nums) > 0: if self.check_strList(content, self.MinKeywords): action.Detail = "母乳:" + nums[0] + u"分钟" else: action.Detail = "奶瓶:" + nums[0] + "mL" if self.check_strList(content, self.PowderKeywords): action.Detail += " (奶粉)" elif self.check_strList(msg.RawContent, self.WeeklyReportsKeywords): action.Type = ActionType.WeeklyReports elif self.check_strList(msg.RawContent, self.RemoveKeywords): action.Type = ActionType.Remove elif self.check_strList(msg.RawContent, self.ReportsKeywords): #reports action.Type = ActionType.Reports action.Status = Action.Active elif self.check_strList(msg.RawContent, self.PoopKeywords): action.Type = ActionType.Poop elif self.check_strList(msg.RawContent, self.BathKeywords): action.Type = ActionType.Bath elif self.check_strList(msg.RawContent, self.FallSleepKeywords): lastAct = self.rlSQL.GetSleepStatus() if lastAct.Type == ActionType.WakeUp: action.Type = ActionType.FallSleep else: action.Type = ActionType.ErrStatus action.Detail = "重复的睡觉,上一次是:" action.Detail += lastAct.TimeStamp.strftime( "%H:%M") elif self.check_strList(msg.RawContent, self.WakeUpKeywords): lastAct = self.rlSQL.GetSleepStatus() if lastAct.Type == ActionType.FallSleep: action.Type = ActionType.WakeUp self.get_latest_sleep(action, num2d, ect) else: action.Type = ActionType.ErrStatus action.Detail = "重复的睡醒,上一次是:" action.Detail += lastAct.TimeStamp.strftime( "%H:%M") elif self.check_strList(msg.RawContent, self.ViewNotesKeywords): action.Type = ActionType.ViewNotes elif self.check_strList(msg.RawContent, self.DebugMsgKeywords): action.Type = ActionType.DebugMsg elif self.check_strList(msg.RawContent, self.FixInputKeywords): action.LoadFromString(msg.RawContent) elif self.check_strList(msg.RawContent, self.PillsKeywords): action.Type = ActionType.Pills start = content.index("药") detail = content[start+1:].strip() action.Detail = detail elif self.check_strList(msg.RawContent, self.ListImageKeywords): action.Type = ActionType.ListImage files = cn_utility.listimgfiles(config.ImageRoot, 7) action.ImageList = [] for f in files: action.ImageList.append((f[5:16], \ "http://stansunlog.eastasia.cloudapp.azure.com/robert_image?name="+f)) else: action.Type = ActionType.UnKnown try: int(msg.RawContent) msgs = self.rlSQL.GetMsgFromUser(msg.FromUser, 2) if self.check_strList(msgs[1].RawContent, self.RemoveKeywords): action.Type = ActionType.RemoveSpecific except ValueError: pass if action.FromUser not in self.users_can_write and action.Type not in \ {ActionType.Reports, ActionType.WeeklyReports, ActionType.ListImage}: action.Type = ActionType.NoPermission return action def get_latest_sleep(self, action, num2d, ect): sleep = self.rlSQL.GetLastFallSleep() if not sleep: action.Type = ActionType.UnKnown else: #check previous time pre_content = num2d.replace_cn_digital(sleep.Detail) sleep_t = ect.extract_time(pre_content, sleep.TimeStamp) if sleep_t is None or len(sleep_t) <= 0: sleep_t = sleep.TimeStamp else: sleep_t = sleep_t[0] delta_minutes = int((action.TimeStamp - sleep_t).total_seconds()/60) action.Detail = "从{0}到{1},睡了{2}小时{3}分钟".format(sleep_t.strftime( "%H:%M"), \ action.TimeStamp.strftime( "%H:%M"), int(delta_minutes/60), delta_minutes%60) ImageFileTemplate = config.ImageRoot + r"{0}_{1}.jpg" def process_img_post(self, msg): timag_name = "D:\\tmp\\{0}_{1}.jpg".format(msg.TimeStamp.strftime("%Y_%m_%d_%H_%M"), msg.MediaId[:6]) img_name = self.ImageFileTemplate.format(msg.TimeStamp.strftime("%Y_%m_%d_%H_%M"), msg.MediaId[:6]) urllib.request.urlretrieve(msg.PicUrl, timag_name) cn_utility.reshapimg(timag_name, img_name) return "收到照片" def GenResponse(self, action): response = "抱歉没听懂." if action.Type == ActionType.Feed: response = "收到,萝卜在{1}吃了{0}".format(action.Detail, action.TimeStamp.strftime( "%H:%M")) elif action.Type == ActionType.Reports: response = "统计结果:" cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) actions = self.rlSQL.GetActionReports(30) actions.sort(key=lambda a:a.TimeStamp) lastmilk = sleepstatus = Action() for a in actions: if a.Status == Action.Deleted: continue if a.Type == ActionType.FallSleep: sleepstatus = a continue elif a.Type == ActionType.WakeUp: sleepstatus = a elif a.Type == ActionType.Feed: lastmilk = a if a.Type not in self.actiontype_skip_log : if a.TimeStamp.day != cur.day: cur = a.TimeStamp response += "\n{0}日(第{1}天)记录:\n".format(cur.strftime("%m-%d"), \ config.get_days_to_birth(cur)) if len(response) > 250: response = response[-250:] response += (a.GenBrief() + "\n") tnow = cn_utility.GetNowForUTC8() if sleepstatus.Type == ActionType.FallSleep: #is sleeping response += (sleepstatus.GenBrief() + "\n") elif sleepstatus.Type == ActionType.WakeUp: delta_minutes = int((tnow - sleepstatus.TimeStamp).total_seconds()/60) if delta_minutes > 240: response += "\n醒了{0}小时{1}分钟了,该睡了".format(int(delta_minutes/60), delta_minutes%60) else: #don't find last status skip pass #disable milk alert for now #delta_minutes = int((tnow - lastmilk.TimeStamp).total_seconds()/60) #if delta_minutes > 240: #response += "\n上次喂奶是{0}小时{1}分钟前:{2}".format(int(delta_minutes/60), delta_minutes%60, lastmilk.GenBrief()) elif action.Type == ActionType.WeeklyReports: response = "统计结果: \n" cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) actions = self.rlSQL.GetActionReports(300) milk = 0 breast = 0 breastNum = 0 poop = 0 sleep = 0 daysShown = 0 pillstaken = 0 comFoodCount = 0 snackCount = 0 notesPerDay = "" for a in actions: if a.Status == Action.Deleted: continue if a.TimeStamp.day != cur.day and (milk !=0 or breast !=0): #response += "{0}日:奶瓶{1}mL,母乳{2}次共{3}分钟,睡觉{5}小时{6}分钟,大便{4}次\n".format(\ #cur.strftime("%m-%d"), milk, breastNum, breast, poop, int(sleep/60), sleep%60) #no breast milk version response += "{0}日:奶瓶{1}mL,辅食{5}次,零食{6}次,睡觉{3}小时{4}分钟,大便{2}次\n".format(\ cur.strftime("%m-%d"), milk, poop, int(sleep/60), sleep%60, comFoodCount, snackCount) if len(notesPerDay) > 0: response += "今日备注: {0}\n".format(notesPerDay) if pillstaken > 0: response += "吃药{0}次\n".format(pillstaken) milk = 0 breast = 0 poop = 0 breastNum = 0 sleep = 0 pillstaken = 0 comFoodCount = 0 snackCount = 0 notesPerDay = "" daysShown += 1 if daysShown >= 8 : break cur = a.TimeStamp if a.Type == ActionType.Feed: nums = re.findall(r"\d+",a.Detail) if len(nums) > 0: d = int(nums[0]) if a.Detail.find("母乳") >= 0: breast += d breastNum += 1 elif a.Detail.find("奶瓶") >= 0: milk += d elif a.Type == ActionType.Poop: poop += 1 elif a.Type == ActionType.WakeUp: ect = extract_cn_time() sleep += ect.extract_time_delta(a.Detail) #print(cur, sleep, a.Detail) elif a.Type == ActionType.ComFood: comFoodCount += 1 elif a.Type == ActionType.Snacks: snackCount += 1 elif a.Type == ActionType.Pills: pillstaken += 1 elif a.Type == ActionType.Notes: #notesPerDay += "{0}日{1}\t".format(cur.strftime("%m-%d"),a.GenBrief()) notesPerDay += a.GenBrief() pass if (milk !=0 or breast !=0) and daysShown < 7: #response += "{0}日:奶瓶{1}mL,母乳{2}次共{3}分钟,睡觉{5}小时{6}分钟,大便{4}次\n".format(\ # cur.strftime("%m-%d"), milk, breastNum, breast, poop, int(sleep/60), sleep%60) #no breast version response += "{0}日:奶瓶{1}mL,辅食{5}次,零食{6}次,睡觉{3}小时{4}分钟,大便{2}次\n".format(\ cur.strftime("%m-%d"), milk, poop, int(sleep/60), sleep%60, comFoodCount, snackCount) if len(notesPerDay) > 0: response += "今日备注: {0}\n".format(notesPerDay) if pillstaken > 0: response += "吃药{0}次\n".format(pillstaken) elif action.Type == ActionType.Remove: response = "请输入要删除的项目序号\n" actions = self.rlSQL.GetActionReports(6) actions.sort(key=lambda a:a.TimeStamp) for a in actions: if a.Status == Action.Deleted: continue response += "序号:{0} 内容:{1},{2}\n".format(\ a.ActionID, self.user_mapping.get(a.FromUser, a.FromUser), a.GenBrief()) elif action.Type == ActionType.RemoveSpecific: self.rlSQL.DeleteAction(int(action.message.RawContent)) response ="已删除一条记录.\n" elif action.Type == ActionType.ListImage: return action.ImageList elif action.Type == ActionType.DebugMsg: msg_list = self.rlSQL.GetLastNumMsg(30) response = "List:\n" for m in msg_list: response +="[{0}] {1}:{2} \n".format(m.TimeStamp.strftime( "%H:%M"), self.user_mapping.get(m.FromUser, m.FromUser), m.RawContent) elif action.Type == ActionType.NoPermission: response = "抱歉您没有权限,可以尝试 '总结' 或 '一周总结' 查看萝卜成长状态。" elif action.Type == ActionType.ComFoodList: response = "吃饭记录:\n" foodList = self.rlSQL.GetActionList( ActionType.ComFood, 80) foodList.sort(key=lambda a:a.TimeStamp) cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) for f in foodList: if f.TimeStamp.day != cur.day: #a new day response += "\n[{0}] {1} ".format(f.TimeStamp.strftime("%m-%d"), f.Detail) cur = f.TimeStamp else: response += f.Detail #f.GenBrief() elif action.Type == ActionType.ViewNotes: response = "备注记录:\n" noteList = self.rlSQL.GetActionList( ActionType.Notes, 5) noteList.sort(key=lambda a:a.TimeStamp) cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) for f in noteList: if f.TimeStamp.day != cur.day: #a new day response += "\n[{0}] {1} ".format(f.TimeStamp.strftime("%m-%d"), f.Detail) cur = f.TimeStamp else: response += f.Detail #f.GenBrief() else: response = action.GenBrief() response += warning.GetWarnings(self.rlSQL) return response lastMsgID = "None" def Receive(self, raw_str): msg = Message(raw_str) if self.lastMsgID == msg.MsgId : logger.error("drop msg id:{0}".format(msg.MsgId)) return #dedup message retry else: self.lastMsgID = msg.MsgId logger.error("going to process msg id:{0}".format(msg.MsgId)) msgs = self.rlSQL.GetMsgFromUser(msg.FromUser, 10) isDup = False for m in msgs: if m.RawContent == msg.RawContent and abs((m.TimeStamp - msg.TimeStamp).total_seconds()) < 10 and m.RawContent.find("总结") < 0: isDup = True logger.error("find dup id:{0}".format(msg.MsgId)) self.rlSQL.LogMessage(msg) if isDup: return if msg.MsgType == "image": return self.process_img_post(msg) action = self.DetectAction(msg) if action.Type not in self.actiontype_skip_log : self.rlSQL.AppendAction(action) else: pass return self.GenResponse(action)
from dbWrapper import RobertLogMSSQL import config import cn_utility import datetime import csv from azure.cosmosdb.table.tableservice import TableService from azure.cosmosdb.table.models import Entity from flask import Flask from flask import render_template from jinja2 import PackageLoader,Environment,FileSystemLoader import json app = Flask(__name__) rlSQL = RobertLogMSSQL(host=config.db_server,user=config.db_user,pwd=config.db_pwd,db="robertlog") azuretable_service = TableService( \ account_name=config.azuretable_account, account_key=config.azuretable_key) def GenLocalStroyLine(month, actions): file_name = config.StoryLineName + month.strftime("%Y_%m") env = Environment(loader=FileSystemLoader('./templates')) template = env.get_template('storyline.ret') html = template.render(MONTH = month, ACTIONS = actions) with open( file_name, 'w', encoding='utf-8') as htmlout: htmlout.write(html) def enumPartition(partition):
from dbWrapper import RobertLogMSSQL from actionCenter import ActionCenter import xml.etree.ElementTree as ET import config from cn_utility import num_cn2digital, extract_cn_time import cn_utility from flask import render_template, Flask import reporting import warning actCenter = ActionCenter() ms = RobertLogMSSQL(host=config.db_server, user=config.db_user, pwd=config.db_pwd, db="radishlog") str_feedcmd_xml = "<xml><ToUserName><![CDATA[fromUser]]></ToUserName>" +\ "<FromUserName><![CDATA[toUser]]></FromUserName>" +\ "<CreateTime>123445</CreateTime>" +\ "<MsgType><![CDATA[text]]></MsgType>"+\ "<Content><![CDATA[两点半喂了200]]></Content>"+\ "</xml>" str_cmdtemplate_xml = "<xml><ToUserName><![CDATA[fromUser]]></ToUserName>" +\ "<FromUserName><![CDATA[toUser]]></FromUserName>" +\ "<CreateTime>123445</CreateTime>" +\ "<MsgType><![CDATA[text]]></MsgType>"+\ "<Content><![CDATA[{0}]]></Content>"+\ "</xml>"
class ActionCenter: #SQL rlSQL = RobertLogMSSQL(host=config.db_server, user=config.db_user, pwd=config.db_pwd, db="robertlog") #Action List FeedKeywords = {u"吃了", u"喂了", u"喂奶", u"吃奶"} ReportsKeywords = {u"报告", u"总结", u"情况"} WeeklyReportsKeywords = {u"一周报告", u"一周总结", u"一周情况", u"本周总结"} NotesKeywords = {u"备注", u"笔记"} mLKeywords = {u"ml", u"毫升"} MinKeywords = {u"分钟"} ADKeywords = {u"AD", u"吃药", u"ad", u"喂药"} PoopKeywords = { u"拉屎", u"大便", } BathKeywords = {u"洗澡"} RemoveKeywords = {u"撤销", u"删除"} FallSleepKeywords = {u"睡着"} #, u"睡觉"} WakeUpKeywords = {u"醒了", u"睡醒"} ListImageKeywords = {u"看照片"} ListSleepTimeKeywords = {u"几点睡", u"睡多久", u"睡了多久"} DebugMsgKeywords = {u"调试消息"} EatCaKeywords = {u"补钙", u"钙片"} ComFoodKeywords = [u"辅食"] ComFoodListKeywords = {u"食谱"} users_can_write = {"fake_weichat_id"} user_mapping = {"fake_weichat_id": "Mom"} actiontype_skip_log = {ActionType.UnKnown, ActionType.Reports, ActionType.WeeklyReports,\ ActionType.Remove, ActionType.NoPermission, ActionType.ListImage, \ ActionType.SleepTime, ActionType.DebugMsg, ActionType.RemoveSpecific, \ ActionType.ErrStatus, ActionType.ComFoodList} def check_strList(self, str, listStr): for s in listStr: if str.find(s) >= 0: return True return False def DetectAction(self, msg): action = Action(msg) num2d = num_cn2digital() ect = extract_cn_time() content = num2d.replace_cn_digital(msg.RawContent) t = ect.extract_time(content) if t is not None and len(t) > 0: action.TimeStamp = t[0] content = ect.remove_time(content) if self.check_strList(msg.RawContent, self.NotesKeywords): action.Type = ActionType.Notes action.Detail = msg.RawContent for k in self.NotesKeywords: action.Detail = action.Detail.lstrip(k) elif self.check_strList(msg.RawContent, self.ListSleepTimeKeywords): action.Type = ActionType.SleepTime self.get_latest_sleep(action, num2d, ect) elif self.check_strList(msg.RawContent, self.ADKeywords): action.Type = ActionType.AD elif self.check_strList(msg.RawContent, self.EatCaKeywords): action.Type = ActionType.EatCa elif self.check_strList(msg.RawContent, self.ComFoodListKeywords): action.Type = ActionType.ComFoodList elif self.check_strList(msg.RawContent, self.ComFoodKeywords): action.Type = ActionType.ComFood start = content.index(self.ComFoodKeywords[0]) detail = content[start + 2:].strip() action.Detail = detail elif self.check_strList(content, self.FeedKeywords): #feed action.Type = ActionType.Feed action.Status = Action.Active nums = re.findall(r"\d+", content) if len(nums) > 0: if self.check_strList(content, self.MinKeywords): action.Detail = "母乳:" + nums[0] + u"分钟" else: action.Detail = "奶瓶:" + nums[0] + "mL" elif self.check_strList(msg.RawContent, self.WeeklyReportsKeywords): action.Type = ActionType.WeeklyReports elif self.check_strList(msg.RawContent, self.RemoveKeywords): action.Type = ActionType.Remove elif self.check_strList(msg.RawContent, self.ReportsKeywords): #reports action.Type = ActionType.Reports action.Status = Action.Active elif self.check_strList(msg.RawContent, self.PoopKeywords): action.Type = ActionType.Poop elif self.check_strList(msg.RawContent, self.BathKeywords): action.Type = ActionType.Bath elif self.check_strList(msg.RawContent, self.FallSleepKeywords): lastAct = self.rlSQL.GetSleepStatus() if lastAct.Type == ActionType.WakeUp: action.Type = ActionType.FallSleep else: action.Type = ActionType.ErrStatus action.Detail = "重复的睡觉,上一次是:" action.Detail += lastAct.TimeStamp.strftime("%H:%M") elif self.check_strList(msg.RawContent, self.WakeUpKeywords): lastAct = self.rlSQL.GetSleepStatus() if lastAct.Type == ActionType.FallSleep: action.Type = ActionType.WakeUp self.get_latest_sleep(action, num2d, ect) else: action.Type = ActionType.ErrStatus action.Detail = "重复的睡醒,上一次是:" action.Detail += lastAct.TimeStamp.strftime("%H:%M") elif self.check_strList(msg.RawContent, self.DebugMsgKeywords): action.Type = ActionType.DebugMsg elif self.check_strList(msg.RawContent, self.ListImageKeywords): action.Type = ActionType.ListImage files = cn_utility.listimgfiles(config.ImageRoot, 7) action.ImageList = [] for f in files: action.ImageList.append((f[5:16], \ "http://<yourhost>.eastasia.cloudapp.azure.com/robert_image?name="+f)) #TODO::load from config else: action.Type = ActionType.UnKnown try: int(msg.RawContent) msgs = self.rlSQL.GetMsgFromUser(msg.FromUser, 2) if self.check_strList(msgs[1].RawContent, self.RemoveKeywords): action.Type = ActionType.RemoveSpecific except ValueError: pass if action.FromUser not in self.users_can_write and action.Type not in \ {ActionType.Reports, ActionType.WeeklyReports, ActionType.ListImage}: action.Type = ActionType.NoPermission return action def get_latest_sleep(self, action, num2d, ect): sleep = self.rlSQL.GetLastFallSleep() if not sleep: action.Type = ActionType.UnKnown else: #check previous time pre_content = num2d.replace_cn_digital(sleep.RawContent) sleep_t = ect.extract_time(pre_content, sleep.TimeStamp) if sleep_t is None or len(sleep_t) <= 0: sleep_t = sleep.TimeStamp else: sleep_t = sleep_t[0] delta_minutes = int( (action.TimeStamp - sleep_t).total_seconds() / 60) action.Detail = "从{0}到{1},睡了{2}小时{3}分钟".format(sleep_t.strftime( "%H:%M"), \ action.TimeStamp.strftime( "%H:%M"), int(delta_minutes/60), delta_minutes%60) ImageFileTemplate = config.ImageRoot + r"{0}_{1}.jpg" def process_img_post(self, msg): timag_name = "D:\\tmp\\{0}_{1}.jpg".format( msg.TimeStamp.strftime("%Y_%m_%d_%H_%M"), msg.MediaId[:6]) img_name = self.ImageFileTemplate.format( msg.TimeStamp.strftime("%Y_%m_%d_%H_%M"), msg.MediaId[:6]) urllib.request.urlretrieve(msg.PicUrl, timag_name) cn_utility.reshapimg(timag_name, img_name) return "收到照片" def GenResponse(self, action): response = "抱歉没听懂." if action.Type == ActionType.Feed: response = "收到,萝卜在{1}吃了{0}".format( action.Detail, action.TimeStamp.strftime("%H:%M")) elif action.Type == ActionType.Reports: response = "统计结果:" cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) actions = self.rlSQL.GetActionReports(30) actions.sort(key=lambda a: a.TimeStamp) lastmilk = sleepstatus = None for a in actions: if a.Status == Action.Deleted: continue if a.Type == ActionType.FallSleep: sleepstatus = a continue elif a.Type == ActionType.WakeUp: sleepstatus = a elif a.Type == ActionType.Feed: lastmilk = a if a.Type not in self.actiontype_skip_log: if a.TimeStamp.day != cur.day: cur = a.TimeStamp response += "\n{0}日(第{1}天)记录:\n".format(cur.strftime("%m-%d"), \ config.get_days_to_birth(cur)) response += (a.GenBrief() + "\n") tnow = cn_utility.GetNowForUTC8() if sleepstatus.Type == ActionType.FallSleep: #is sleeping response += (sleepstatus.GenBrief() + "\n") else: delta_minutes = int( (tnow - sleepstatus.TimeStamp).total_seconds() / 60) if delta_minutes > 150: response += "\n醒了{0}小时{1}分钟了,该睡了".format( int(delta_minutes / 60), delta_minutes % 60) delta_minutes = int( (tnow - lastmilk.TimeStamp).total_seconds() / 60) if delta_minutes > 150: response += "\n上次喂奶是{0}小时{1}分钟前:{2}".format( int(delta_minutes / 60), delta_minutes % 60, lastmilk.GenBrief()) elif action.Type == ActionType.WeeklyReports: response = "统计结果: \n" cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) actions = self.rlSQL.GetActionReports(300) milk = 0 breast = 0 breastNum = 0 poop = 0 sleep = 0 daysShown = 0 for a in actions: if a.Status == Action.Deleted: continue if a.TimeStamp.day != cur.day and (milk != 0 or breast != 0): response += "{0}日:奶瓶{1}mL,母乳{2}次共{3}分钟,睡觉{5}小时{6}分钟,大便{4}次\n".format(\ cur.strftime("%m-%d"), milk, breastNum, breast, poop, int(sleep/60), sleep%60) milk = 0 breast = 0 poop = 0 breastNum = 0 sleep = 0 daysShown += 1 if daysShown >= 8: break cur = a.TimeStamp if a.Type == ActionType.Feed: nums = re.findall(r"\d+", a.Detail) if len(nums) > 0: d = int(nums[0]) if a.Detail.find("母乳") >= 0: breast += d breastNum += 1 elif a.Detail.find("奶瓶") >= 0: milk += d elif a.Type == ActionType.Poop: poop += 1 elif a.Type == ActionType.WakeUp: ect = extract_cn_time() sleep += ect.extract_time_delta(a.Detail) #print(cur, sleep, a.Detail) elif a.Type == ActionType.Notes: #response += "{0}日{1}\n".format(cur.strftime("%m-%d"),a.GenBrief()) pass if (milk != 0 or breast != 0) and daysShown < 7: response += "{0}日:奶瓶{1}mL,母乳{2}次共{3}分钟,睡觉{5}小时{6}分钟,大便{4}次\n".format(\ cur.strftime("%m-%d"), milk, breastNum, breast, poop, int(sleep/60), sleep%60) elif action.Type == ActionType.Remove: response = "请输入要删除的项目序号\n" actions = self.rlSQL.GetActionReports(6) actions.sort(key=lambda a: a.TimeStamp) for a in actions: if a.Status == Action.Deleted: continue response += "序号:{0} 内容:{1},{2}\n".format(\ a.ActionID, self.user_mapping.get(a.FromUser, a.FromUser), a.GenBrief()) elif action.Type == ActionType.RemoveSpecific: self.rlSQL.DeleteAction(int(action.message.RawContent)) response = "已删除一条记录.\n" elif action.Type == ActionType.ListImage: return action.ImageList elif action.Type == ActionType.DebugMsg: msg_list = self.rlSQL.GetLastNumMsg(30) response = "List:\n" for m in msg_list: response += "[{0}] {1}:{2} \n".format( m.TimeStamp.strftime("%H:%M"), self.user_mapping.get(m.FromUser, m.FromUser), m.RawContent) elif action.Type == ActionType.NoPermission: response = "抱歉您没有权限,可以尝试 '总结' 或 '一周总结' 查看萝卜成长状态。" elif action.Type == ActionType.ComFoodList: foodList = self.rlSQL.GetActionList(ActionType.ComFood, 80) foodList.sort(key=lambda a: a.TimeStamp) cur = datetime.datetime.utcnow() + datetime.timedelta(days=2) for f in foodList: if f.TimeStamp.day != cur.day: #a new day response += "\n[{0}] {1} ".format( f.TimeStamp.strftime("%m-%d"), f.Detail) cur = f.TimeStamp else: response += f.Detail #f.GenBrief() else: response = action.GenBrief() response += warning.GetWarnings(self.rlSQL) return response def Receive(self, raw_str): msg = Message(raw_str) self.rlSQL.LogMessage(msg) if msg.MsgType == "image": return self.process_img_post(msg) action = self.DetectAction(msg) if action.Type not in self.actiontype_skip_log: self.rlSQL.AppendAction(action) else: pass return self.GenResponse(action)