# coding=utf-8 import datetime import logging from django.db.models import Q from gm_types.error import ERROR as CODES from gm_types.gaia import DIARY_OPERATION, PLATFORM_CHANNEL, DOCTOR_PROCESS_STATUS from gm_types.gaia import PROBLEM_FLAG_CHOICES, PRIVATE_STATUS, TOPIC_TYPE, FILTER_WORD_TYPE from gm_types.mimas import TRACTATE_SORT_TYPE from gm_types.user_hierarchy import EventType from talos.tools.hospital_tool import HospitalTool from ..models.topic import TopicScore, TopicReply, Problem from talos.models.doctor import DoctorMessageList from talos.libs.diaryrank_utils import DiaryRankTool from talos.libs.reply import is_reply_num_gt_limit from talos.services import DoctorService from talos.tasks import push_diary_reply_message, applet_topic_replied_push, applet_topic_reply_summary_push from talos.tools.filterword_tool import filterword_by_custom from utils.rpc import gen, rpc_client, logging_exception from user_hierarchy.portal import process_task from utils.stat_log import SocialStatLogForUserAction def update_topic_score(user_id, topic, score): topic_score, created = TopicScore.objects.get_or_create(topic=topic, user_id=user_id) topic_score.score = score topic_score.save() return topic_score.id def topic_reply_common(user, topic_id, reply_id=None, content='', device_id=None, platform_channel=None): # from ..models.topic import Problem # TODO: user """话题回复. :param content: 回复的内容, :param reply_id: 评论ID,可选. 回复帖子时, 该字段为None; 回复其他评论时, 不可为空 :param topic_id: 话题ID, 必选 :param user: 用户 """ result = { 'comment_data': {}, 'reply_data': {}, 'topic': {}, 'doctor': {}, # if user is a doctor, add doctor.id } # check if content is empty if not content.strip(): return gen(CODES.REPLY_CAN_NOT_BE_EMPTY) # 检查用户在一分钟内回复(日记本/帖子)是否大于3条 if is_reply_num_gt_limit(user=user): return gen(CODES.COMMENT_BUSY) replied_reply = None if reply_id: replied_reply = TopicReply.objects.filter(id=reply_id).first() # get right topic if replied_reply and replied_reply.problem: topic = replied_reply.problem else: try: topic = Problem.objects.get(id=topic_id) except Problem.DoesNotExist: topic = None if not topic: return gen(CODES.TOPIC_NOT_FOUND) # check if user is not in one organize if topic.topic_type == TOPIC_TYPE.SHARE and not HospitalTool.in_one_hospital(topic, user.id): return gen(CODES.TOPIC_REPLY_BAN_NOT_OWN) result['topic']['id'] = topic.id result['topic']['ask'] = topic.ask result['topic']['topic_type'] = topic.topic_type result['topic']['tags'] = topic.get_tags() doctors = DoctorService.get_doctor_from_user_ids(user_ids=[user.id]) doctor = doctors[0] if doctors else None if not (topic.flag == PROBLEM_FLAG_CHOICES.NORMAL or topic.is_online): return gen(CODES.TOPIC_HAS_BEEN_DELETED) #以前的代码进行了数字的过滤,本次沿用以前的逻辑 filterword_by_custom(filter_type=FILTER_WORD_TYPE.TOPIC_REPLY, content=content) # check if content is same as the previous reply try: reply = TopicReply.objects.filter(problem=topic, user_id=user.id) last_id = reply.latest('id') previous_reply = TopicReply.objects.get(id=last_id.id) if previous_reply.content == content: return gen(CODES.REPLY_CAN_NOT_BE_REPEATED) except TopicReply.DoesNotExist: pass d = topic.diary if d is not None: if d.user_id == user.id: if reply_id and replied_reply: d = DiaryRankTool(d.id) t = datetime.datetime.now() replied_user_id = replied_reply.user_id d.add_heat(DIARY_OPERATION.SELF_REPLY, t, extra_id=replied_user_id) elif device_id: d = DiaryRankTool(d.id) t = datetime.datetime.now() d.add_heat(DIARY_OPERATION.OTHER_REPLY, t, extra_id=device_id) topic.reply_num += 1 if topic.user_id == user.id: topic.author_reply_num += 1 if doctor: result['doctor']['id'] = doctor.id # 限制民营医院医生 if topic.private_status == PRIVATE_STATUS.NORMAL: reply_filter = Q(doctor_id=doctor.id) & Q( problem__private_status=PRIVATE_STATUS.NORMAL) today_reply_amount = TopicReply.objects.filter(reply_filter).extra( where=['date(reply_date)=CURRENT_DATE'] ).count() if today_reply_amount >= doctor.reply_limit: return gen(CODES.DOCTOR_REPLY_TOPIC_LIMITED) rpc_client['doctor/update_last_answered_time'](doctor_id=doctor.id).unwrap() # 如果是医生的回复,就把该问题标记成已经回答 topic.has_answer = True # TODO 一个医生回答多次只记录一次 if topic.private_status == PRIVATE_STATUS.ASSIGN_DOCTOR_PRIVATE: topic.private_status = PRIVATE_STATUS.ASSIGN_DOCTOR_PRIVATE_ANSWERED elif topic.private_status == PRIVATE_STATUS.ASSIGN_DOCTOR: topic.private_status = PRIVATE_STATUS.ASSIGN_DOCTOR_ANSWERED topic.doctor_num += 1 topic.save() doctor_today_reply_amount = TopicReply.objects.filter( doctor_id=doctor.id, reply_date__gt=datetime.date.today() ).count() result['doctor']['today_reply_count'] = doctor_today_reply_amount if not topic.is_topic and not topic.answer: topic.answer = content topic.assigned_doctor_id = user.id # TODO: check topic.has_answer = True topic.reply_num = 1 topic.doctor_num = 1 topic.save() commented_reply = None if replied_reply: if replied_reply.commented_reply: commented_reply = replied_reply.commented_reply else: commented_reply = replied_reply topic_reply = TopicReply() topic_reply.problem = topic topic_reply.user_id = user.id topic_reply.doctor_id = doctor.id if doctor else None topic_reply.content = content topic_reply.replied_topic = replied_reply topic_reply.commented_reply = commented_reply topic_reply.save() # 给被评论的用户发小程序push applet_topic_replied_push.delay(topic_reply.id) # 24小时后,如果当前评论没有收到评论或点赞,则给当前评论用户发送相关小程序push applet_topic_reply_summary_push.apply_async((topic_reply.id,), countdown=86400) comment_reply_id = topic_reply.id if not reply_id else reply_id if doctor: DoctorMessageList.objects.filter(topic_id=topic.id, doctor_id=doctor.id, process_status=DOCTOR_PROCESS_STATUS.unprocessed).\ update(process_status=DOCTOR_PROCESS_STATUS.processed) if topic.diary: from talos.cache.takesofacache import take_sofa_cache take_sofa_cache.del_diary_cache_data(topic.diary_id) if doctor: update_topic_score(doctor.user_id, topic, 0) elif replied_reply: try: is_doctor = DoctorService.get_doctor_by_user_id(user_id=replied_reply.user_id) is_doctor = bool(is_doctor) except IndexError: is_doctor = False if is_doctor: update_topic_score(replied_reply.user_id, topic, 3) topic.save() logging.info("create new reply, topic id is: {}, reply id is: {}".format( topic.id, topic_reply.id)) replied_reply_user_id = replied_reply.user_id if replied_reply else None topic_user_id = topic.user_id if topic else None push_diary_reply_message(user_id=user.id, content=content, reply_id=comment_reply_id, topic_id=topic.id, replied_reply_user_id=replied_reply_user_id, topic_user_id=topic_user_id) # 返回本身的数据 try: reply_data = topic_reply.reply_data_after_create() except: reply_data = {} logging_exception() try: comment_data = topic_reply.comment_data_after_create() except: logging_exception() comment_data = {} # 新加评论时,2h随机加赞2-4 # 产品需求, 将这段逻辑删除, 暂时保留防止有用 """ try: repeat_times, countdown = get_async_args( const_strings.TOPIC_REPLY_FAKE_VOTE) fake_vote.apply_async(args=(repeat_times, topic), countdown=countdown) except: logging_exception() """ # 用户行为埋点,评论相关 _topic_type = topic.topic_type if _topic_type in [TOPIC_TYPE.ASK, TOPIC_TYPE.SHARE, TOPIC_TYPE.TOPIC]: # 日记帖 _stat_log_data = { "user_id": user.id, "content_id": topic.diary_id, "content_type": SocialStatLogForUserAction.CONTENT_TYPE.diary } elif _topic_type in [TOPIC_TYPE.USER_ARTICLE, TOPIC_TYPE.COLUMN_ARTICLE]: # 专栏 _stat_log_data = { "user_id": user.id, "content_id": topic.id, "content_type": SocialStatLogForUserAction.CONTENT_TYPE.article } else: _stat_log_data = {} if _stat_log_data: SocialStatLogForUserAction.stat_log_for_reply(**_stat_log_data) # add point, growth growth_value, point_value, submit_count = 0, 0, 0 # if len(set(word for word in content)) > 5: if not replied_reply and user.id != topic.user_id \ and topic.topic_type in [TOPIC_TYPE.ASK, TOPIC_TYPE.SHARE, TOPIC_TYPE.COLUMN_ARTICLE]: # event_data = rpc_client['mimas/user/process_event_task']( # user_id=user.id, event_type=EventType.COMMENT_OTHER, related_item=topic_reply.id).unwrap() event_data = process_task(user_id=user.id, event_type=EventType.COMMENT_OTHER, related_item=topic_reply.id) growth_value, point_value, submit_count = event_data['growth_value'], event_data['point_value'], event_data[ 'submit_count'] result['comment_data'] = comment_data result['reply_data'] = reply_data result['point_value'] = point_value result['growth_value'] = growth_value result['submit_count'] = submit_count return result def get_xcx_topic_reply(start_num, count, user, topic, sort_type, comment_id): """ 获取日记帖的评论 :param start_num: :param count: :param user: :param topic: :param sort_type: :return: """ replies_list = [] if topic and topic.is_online and topic.flag == PROBLEM_FLAG_CHOICES.NORMAL: query = Q(problem_id=topic.id, commented_reply_id__isnull=True, is_online=True) # 小程序获取最新评论 if sort_type in [TRACTATE_SORT_TYPE.NEWEST]: replies = TopicReply.objects.filter(query).order_by('-id') else: # 默认获取最热 replies = TopicReply.objects.filter(query).order_by('-like_num', 'id') replies_list = TopicReply.get_replies_info( user, replies, start_num=start_num, count=count, comment_id=comment_id, is_xcx=True ) return replies_list def get_topic_reply( start_num, count, user, topic_obj=None, topic_id=None, only_doctor_reply=False, is_new=False, comment_id=None, new_sub_comment_count=False ): """ 通过日记帖id or objects,获取该日记帖下的评论 :param topic_obj: 日记帖对象 :param topic_id: 日记帖id :param start_num: 评论起始数 :param count: 个数 :param only_doctor_reply: 仅要医生的回复 :param is_new: 是否取最新评论 :param new_sub_comment_count: 子评论展示个数 :return: result dict """ result = { "topic_replies": [], } if topic_id: # 优先获取topic_id topic = Problem.get_by_id(topic_id) elif topic_obj: topic = topic_obj if topic and topic.is_online and topic.flag == PROBLEM_FLAG_CHOICES.NORMAL: query = Q(problem_id=topic.id, commented_reply_id__isnull=True, is_online=True) if only_doctor_reply: query = Q(doctor_id__isnull=False) & query replies = TopicReply.objects.filter(query) first_reply_count = replies.count() replies = replies[start_num: start_num + count] replies_list = TopicReply.get_replies_info( user, replies, start_num=start_num, count=count, comment_id=comment_id, new_sub_comment_count=new_sub_comment_count ) else: replies = TopicReply.objects.filter(query).order_by("-id") first_reply_count = replies.count() if is_new: replies = replies[start_num: start_num + count] replies_list = TopicReply.get_replies_info( user, replies, start_num=0, count=count, comment_id=comment_id, new_sub_comment_count=new_sub_comment_count ) else: replies_list = TopicReply.get_replies_list_info( user, query, start_num=start_num, count=count, comment_id=comment_id, new_sub_comment_count=new_sub_comment_count ) result['first_reply_count'] = first_reply_count result["topic_replies"] = replies_list return result