# -*- coding: utf-8 -*- from django.conf import settings from django.db.models import Q from gm_types.mimas import ( TRACTATE_PLATFORM, TRACTATE_REPLY_HIGHLIGHT ) from gm_types.error import ERROR as CODES from gm_dataquery.dict_mixin import to_dict from gm_rpcd.all import RPCDFaultException from utils.rpc import gen, get_current_user from utils.stat_log import SocialStatLogForUserAction from talos.cache.base import reply_cache as reply_msg_cache from talos.tools.replies_tool import ReplyTool from talos.views.tractate.tractate import update_tractate_special_info from talos.libs.datetime_utils import get_timestamp_or_none from qa.utils.decorator import listing from talos.rpc import bind_context, bind from talos.services.tractate.tractate import TractateService from talos.services.tractate.reply import TractateReplyService from talos.services.tractate.vote import TractateReplyVoteService from talos.services import get_user_from_context, UserService, UserConvertService from talos.services.doctor import DoctorService from talos.tools.tractate_reply_tool import reply_update_cache, get_reply_ids from talos.tasks.tractate import reply_push uri_pre = 'mimas/tractate_reply/' @bind_context(uri_pre + 'create', with_context=True) def create_tractate_reply(ctx, tractate_id, content, replied_id=None, top_id=None): """回复创建""" user = get_user_from_context(ctx) if not user: return gen(CODES.LOGIN_REQUIRED) tractate = TractateService.healthy(tractate_id) result = { "replied_user_id": "", "replied_user_portrait": "", "replied_user_name": "" } replied = None if not top_id and not replied_id: top_id = 0 if replied_id and not top_id: top_id = replied_id if replied_id: replied_info = TractateReplyService.get_by_id(pk=replied_id) replied_user_info = UserConvertService.get_user_info_by_user_id(replied_info.user_id) result.update({ "replied_user_id": replied_user_info.get("user_id", 0), "replied_user_portrait": replied_user_info.get("portrait", ""), "replied_user_name": replied_user_info.get("user_name", ""), "replied_user_info": replied_user_info, }) reply = TractateReplyService.create( content=content, user_id=user.id, tractate_id=tractate_id, extra={ "top_id": top_id, "replied_id": replied_id, "source_id": TRACTATE_PLATFORM.GM } ) replied_user_id = replied_info.user_id if replied_id else tractate.user_id if user.id != replied_user_id: rt = ReplyTool(reply_msg_cache, replied_user_id) rt.receive_tractate_reply(reply.id) reply_push.delay(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id) # 用户行为埋点 评论相关 SocialStatLogForUserAction.stat_log_for_reply( content_type=SocialStatLogForUserAction.CONTENT_TYPE.user_post, content_id=tractate_id, user_id=user.id ) #更新一级评论下的评论数 if top_id: result.update({"top_id": int(top_id)}) TractateReplyService.update_reply_count(top_reply_id=top_id) else: result.update({"replies": []}) TractateService.incr_tractate_reply(tractate=tractate) reply_update_cache(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id) result.update({ 'id': reply.id, 'content': reply.content, 'create_time': get_timestamp_or_none(reply.create_time), "replied_id": int(replied_id) if replied_id else '', "user_name": user.nickname, "user_id": user.id, "user_portrait": user.portrait, "is_vote": False, "vote_num": 0, "status": TRACTATE_REPLY_HIGHLIGHT.DARK, "reply_count": 0, "reply_user_info": UserConvertService.get_user_info_by_user_id(user.id), }) return result @bind_context(uri_pre + 'receive', with_context=True) def get_replies_by_ids(ctx, replies_ids): user = get_user_from_context(ctx) if not user: return gen(CODES.LOGIN_REQUIRED) if not replies_ids: return {} replies_dict = TractateReplyService.get_replies_info(reply_ids=replies_ids) user_ids = [] replied_ids = [] tractates_ids = [] for _, reply in replies_dict.items(): user_ids.append(reply["user_id"]) replied_ids.append(reply["replied_id"]) tractates_ids.append(reply["tractate_id"]) replied_dict = TractateReplyService.get_replies_info(reply_ids=replied_ids) users_dict = UserService.get_users_by_user_ids(user_ids) tractates_dict = TractateService.list_tractate_by_ids(tractates_ids) doctors_dict = {} doctors = DoctorService.get_doctor_from_user_ids(user_ids) for doctor in doctors: doctors_dict[doctor.user_id] = doctor result = {} for reply_id, reply in replies_dict.items(): reply_user = users_dict.get(reply["user_id"], {}) doctor = doctors_dict.get(reply["user_id"], {}) doctor_info = {} if doctor: doctor_info = { "user_id": doctor.user_id, "doctor_id": doctor.id, "name": doctor.name, } replied = {} if reply["replied_id"]: item = replied_dict.get(reply["replied_id"], {}) if item: replied = { "id": reply["replied_id"], "content": reply["content"], } tractate = {} tractate_obj = tractates_dict.get(reply["tractate_id"]) if tractate_obj: tractate = { "id": tractate_obj.id, "content": tractate_obj.content, "user_id": tractate_obj.user_id } info = { "id": reply["id"], "reply_date": reply["create_time"], "reply_content": reply["content"], "tractate": tractate, "replied": replied, "reply_user": { "id": reply_user.id, "name": reply_user.nickname, "portrait": reply_user.portrait, }, "author": { "id": user.id, "name": user.nickname, "portrait": user.portrait, }, "doctor": doctor_info, } result[str(reply_id)] = info return result @bind(uri_pre + 'top/list') #@listing() def list_top_reply(ctx, tractate_id, offset=0, count=10, sort_condition=None): """一级回复列表""" user = get_user_from_context(ctx) tractate = TractateService.healthy(tractate_id) replies = TractateReplyService.list_top_reply_by_tractate_id(tractate_id, offset, count) user_ids = [reply.get('user_id') for reply in replies] users = UserConvertService.get_user_info_by_user_ids(user_ids) for reply in replies: reply_user_info = users.get(reply.get('user_id'), {}) if not reply_user_info: continue reply.update({ "user_nickname": reply_user_info.get("user_name", ""), "user_portrait": reply_user_info.get("portrait", ""), "reply_user_info": reply_user_info, }) reply_num_total = tractate.reply_num return { 'replies': replies, 'reply_num_total': reply_num_total } @bind(uri_pre + 'second_list') @listing() def gets_second_reply(reply_id, offset=0, count=10, user_id=None, sort_condition=None): """二级回复列表""" second_reply = TractateReplyService.get_second_reply_by_top_id( top_id=int(reply_id), offset=int(offset), count=int(count), sort_condition=sort_condition) user_ids, vote_reply_ids, replied_ids = set(), set(), set() for reply_item in second_reply: _user_id = reply_item.get("user_id", 0) _replied_id = reply_item.get("replied_id", 0) _id = reply_item.get("id", 0) if _user_id: user_ids.add(_user_id) if _replied_id: replied_ids.add(_replied_id) if _id: vote_reply_ids.add(_id) # 评论数据信息 replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids) replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values()) all_user_ids = user_ids | replyed_user_ids users = UserConvertService.get_user_info_by_user_ids(all_user_ids) for reply in second_reply: reply_user_info = users.get(reply.get('user_id', 0), {}) if not reply_user_info: continue replied_info = replied_infos.get(reply.get('replied_id'), {}) replied_user_info = users.get(replied_info.get('user_id', 0), {}) if not replied_user_info: continue reply.update({ "is_vote": True if reply.get('id') in vote_reply_ids else False, "user_name": reply_user_info.get("user_name", ""), "user_portrait": reply_user_info.get("portrait", ""), "replied_user_id": replied_user_info.get("user_id", 0), "replied_user_name": replied_user_info.get("user_name", ""), "replied_user_portrait": replied_user_info.get("portrait", ""), "reply_user_info": reply_user_info, "replied_user_info": replied_user_info, }) return second_reply @bind(uri_pre + 'top_list') @listing() def list_top_reply_by_tractate_ids(tractate_ids, offset=0, count=2, sort_condition=None): """多个帖子一级评论""" result, user_ids = {}, [] for tractate_id in tractate_ids: _replies_list = TractateReplyService.list_top_reply_by_tractate_id( tractate_id=tractate_id, offset=offset, count=count, sort_condition=sort_condition ) user_ids.extend([reply.get('user_id') for reply in _replies_list]) result[str(tractate_id)] = _replies_list users = UserConvertService.get_user_info_by_user_ids(user_ids) for k, item in result.items(): for reply in item: _user_info = users.get(reply.get("user_id", 0), {}) if not _user_info: continue reply.update({ "user_nickname": _user_info.get("user_name", ""), "user_portrait": _user_info.get("portrait", ""), "reply_user_info": _user_info, }) return result @bind(uri_pre + 'reply_popup') @listing() def get_reply_in_popup(tractate_id, offset=0, count=5, user_id=None, sort_condition=None): """评论弹窗~获取评论(一级和二级)""" SECOND_COUNT, START_INDEX = 2, 0 TractateService.healthy(tractate_id) # 一级评论数据 top_reply_infos = TractateReplyService.list_top_reply_by_tractate_id( tractate_id=int(tractate_id), offset=int(offset), count=int(count), sort_condition=sort_condition ) top_reply_user_ids, vote_reply_ids = set(), [] second_user_ids, repied_ids = set(), [] # 一级评论处理用户,点赞状态,二级评论及子评论逻辑 for item in top_reply_infos: _user_id = item.get("user_id", 0) _id = item.get("id", 0) if _user_id: top_reply_user_ids.add(_user_id) if _id: vote_reply_ids.append(_id) # 二级评论 second_reply = TractateReplyService.get_second_reply_by_top_id( top_id=_id, count=SECOND_COUNT, offset=START_INDEX, sort_condition=sort_condition ) # 处理一级评论的子评论 item['replies'] = second_reply for reply in second_reply: _reply_user_id = reply.get("user_id", 0) _replied_id = reply.get("replied_id", 0) _second_reply_id = reply.get("id", 0) if _reply_user_id: second_user_ids.add(_reply_user_id) if _replied_id: repied_ids.append(_replied_id) if _second_reply_id: vote_reply_ids.append(_second_reply_id) # 处理二级评论、被评论用户信息 replied_infos = TractateReplyService.get_replies_info(reply_ids=repied_ids) replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values()) # 取所有用户信息 _all_user_ids = top_reply_user_ids | second_user_ids | replyed_user_ids all_user_infos = UserConvertService.get_user_info_by_user_ids(_all_user_ids) # 取所有已经被点赞的评论id voted_reply_ids = TractateReplyVoteService.get_vote_status( user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids) #评论信息处理 for top_reply_info in top_reply_infos: top_reply_user_info = all_user_infos.get(top_reply_info.get("user_id", 0), {}) if not top_reply_user_info: continue top_reply_info.update({ "user_name": top_reply_user_info.get("user_name", ""), "user_portrait": top_reply_user_info.get("portrait", ""), "is_vote": bool(top_reply_info.get("id", 0) in voted_reply_ids), "top_reply_user_info": top_reply_user_info, }) # 二级评论信息处理 for second_reply in top_reply_info.get('replies', []): second_reply_user_info = all_user_infos.get(second_reply.get("user_id", 0), {}) if not second_reply_user_info: continue replied_info = replied_infos.get(second_reply.get('replied_id'), {}) replied_info_user_info = all_user_infos.get(replied_info.get("user_id", 0), {}) if not replied_info_user_info: continue second_reply.update({ "is_vote": bool(second_reply.get("id", 0) in voted_reply_ids), "user_name": second_reply_user_info.get("user_name", ""), "user_portrait": second_reply_user_info.get("portrait", ""), "replied_user_id": replied_info_user_info.get("user_id", ""), "replied_user_name": replied_info_user_info.get("user_name", ""), "replied_user_portrait": replied_info_user_info.get("portrait", ""), "second_reply_user_info": second_reply_user_info, "replied_user_info": replied_info_user_info, }) return top_reply_infos @bind(uri_pre + 'light_reply') def get_light_reply(tractate_id, user_id=None, target_reply_id=None): """获取高亮评论""" SECOND_COUNT, START_INDEX = 2, 0 more_highlight = True if not target_reply_id: return gen(CODES.PARAMS_INCOMPLETE) top_info = TractateReplyService.get_highlight_reply(target_reply_id=target_reply_id) if not top_info: return [] user_ids, replied_ids, vote_reply_ids = set(), set(), set() user_ids.add(top_info.get('user_id')) vote_reply_ids.add(top_info.get("id")) second_replies = TractateReplyService.get_second_reply_by_top_id( top_id=top_info.get('id'), count=SECOND_COUNT, target_reply_id=target_reply_id) for reply in second_replies: _reply_user_id = reply.get("user_id", 0) _replied_id = reply.get("replied_id", 0) _second_reply_id = reply.get("id", 0) if _reply_user_id: user_ids.add(_reply_user_id) if _replied_id: replied_ids.add(_replied_id) if _second_reply_id: vote_reply_ids.add(_second_reply_id) replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids) for key, value in replied_infos.items(): user_ids.add(value.get('user_id', 0)) #获取用户是否点过赞 voted_reply_ids = TractateReplyVoteService.get_vote_status( user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids ) # 所有用户 all_user = UserConvertService.get_user_info_by_user_ids(user_ids) for second_reply in second_replies: second_reply_user_info = all_user.get(second_reply.get("user_id", 0), {}) if not second_reply_user_info: continue replied_info = replied_infos.get(second_reply.get('replied_id'), {}) replied_info_user_info = all_user.get(replied_info.get("user_id", 0), {}) if not replied_info_user_info: continue if not top_info['status'] and second_reply['status'] == TRACTATE_REPLY_HIGHLIGHT.LIGHT: more_highlight = False second_reply.update({ "is_vote": True if second_reply.get('id') in voted_reply_ids else False, "user_name": second_reply_user_info.get("user_name", ""), "user_portrait": second_reply_user_info.get("portrait", ""), "replied_user_id": replied_info_user_info.get("user_id", ""), "replied_user_name": replied_info_user_info.get("user_name", ""), "replied_user_portrait": replied_info_user_info.get("portrait", ""), "second_reply_user_info": second_reply_user_info, "replied_user_info": replied_info_user_info, }) top_user_info = all_user.get(top_info.get("user_id", 0), {}) top_info.update({ "replies": second_replies, "user_id": top_user_info.get("user_id", 0), "user_name": top_user_info.get("user_name", ""), "user_portrait": top_user_info.get("portrait", ""), "is_vote": True if top_info.get('id') in voted_reply_ids else False, "top_reply_user_info": top_user_info, }) if not top_info['status'] and more_highlight: top_info['status'] = TRACTATE_REPLY_HIGHLIGHT.MORE_LIGHT return [top_info] @bind(uri_pre + 'get_info') def get_reply_by_id(reply_id): if not reply_id: return gen(CODES.PARAMS_INCOMPLETE) reply = TractateReplyService.get_by_id(pk=int(reply_id)) reply = to_dict(reply) user_info = UserConvertService.get_user_info_by_user_id(reply.get('user_id')) reply.update({ "user_nickname": user_info.get("user_name", ""), "user_portrait": user_info.get("portrait", ""), "reply_user_info": user_info, }) return reply @bind(uri_pre + 'get_by_tractate') #@listing() def get_reply_by_tractate(user_id, offset=0, count=10, tractate_from='', use_new_query=False): """ :param user_id: :param offset: :param count: :param tractate_from: 7.12.0 帖子入口 :param use_new_query: 7.12.0 版本兼容 :return: """ if not user_id: return gen(CODES.LOGIN_REQUIRED) data = get_reply_ids(user_id=user_id) dic_reply = data.get('dic_reply') reply_infos = TractateReplyService.get_replies_info(reply_ids=data.get('reply_ids', [])) _tractate_ids = TractateService.get_tractate_ids_by_query_and_order( query=Q(id__in=data.get('tractate_ids', [])), order_by=["-id"], offset=offset, size=count, tractate_from=tractate_from, use_new_query=use_new_query ) tractate_list = [] if _tractate_ids: tractates_info_dic = TractateService.get_tractate_infos_by_ids( tractate_ids=_tractate_ids, need_special_info=True, tractate_from=tractate_from, use_new_query=use_new_query, ) # 增加浏览量 TractateService.tractate_view_increase_num(tractates_info_dic.get("valid_tractate_ids", [])) tractate_list = update_tractate_special_info(tractates_info_dic.get("tractate_list", []), _tractate_ids, user_id) for tractate in tractate_list: if dic_reply.get(tractate.get('tractate_id')): tractate['reply'] = reply_infos.get(dic_reply.get(tractate.get('tractate_id'))) return tractate_list @bind_context(uri_pre + 'received_aggregation', with_context=True) def tractate_reply_reseived_aggregation(ctx): result = { "count": 0, "last_user_info": {}, "create_time": 0, } user = get_user_from_context(ctx) if not user: return result info = TractateReplyService.get_tractate_reply_count_info(user.id) count = info["count"] last_user_id = info["last_user_id"] created_time = info["create_time"] if not count or not last_user_id: return result last_user_info = UserConvertService.get_user_info_by_user_id(last_user_id) result["count"] = count result["create_time"] = get_timestamp_or_none(created_time) _user_info = { "nickname": last_user_info.get("user_name", ""), "portrait": last_user_info.get("portrait", ""), } result["last_user_info"] = _user_info return result @bind(uri_pre + 'read') def tractate_reply_read(): user = get_current_user() if not user: return TractateReplyService.read_all(user.id)