from collections import defaultdict from django.conf import settings from gm_types.gaia import FAVOROBJECT, NotificationType from gm_types.error import ERROR as CODES from gm_rpcd.all import bind from qa.service import QaFavorServices from talos.libs.datetime_utils import get_timestamp_or_none from talos.cache.base import favor_cache from talos.decorators import list_interface from talos.models.diary import DiaryFavor from talos.models.topic import ProblemFavor from talos.manager import diary_list_manager, topic_list_manager from talos.services.tractate import TractateFavorService from talos.services.tractate import TractateService from talos.services import ( UserService, UserConvertService, ) from talos.tools.favor_tool import FavorTool from utils.rpc import gen, get_current_user def get_user_unread_favor_count(user_id): diary_favor = DiaryFavor.list_unread(user_id) if diary_favor: df_unread_count = diary_favor.count() else: df_unread_count = 0 problem_favor = ProblemFavor.list_unread(user_id) if problem_favor: pf_unread_count = ProblemFavor.list_unread(user_id).count() else: pf_unread_count = 0 tf_unread_count = TractateFavorService.get_unread_favorite_num(user_id) q_unread_count = QaFavorServices.get_message_tab_question_favor_count(user_id) a_unread_count = QaFavorServices.get_message_tab_answer_favor_count(user_id) qa_count = q_unread_count.get('count', 0) + a_unread_count.get('count', 0) return df_unread_count + pf_unread_count + tf_unread_count + qa_count def list_tractates_by_favor_ids(favors): tractates = TractateService.list_tractate_by_ids( [item.tractate_id for item in favors] ) return tractates def list_topics_by_favor_ids(favors): topics = topic_list_manager.list_problems_by_ids( [item.problem_id for item in favors] ) return topics def list_diaries_by_favor_ids(favors): diaries = diary_list_manager.list_diaries_by_ids( [item.diary_id for item in favors] ) return diaries def list_question_by_favor_ids(favors): questions = QaFavorServices.get_question_by_ids( [qv.question_id for qv in favors] ) return { question.id: question for question in questions } def list_answer_by_favor_ids(favors): answers = QaFavorServices.get_answer_by_ids( [av.answer_id for av in favors] ) return { answer.id: answer for answer in answers } @bind('mimas/favors/received') def tractate_favor_received(start_num=0, count=10): """消息页面的收藏通知。""" user = get_current_user() if not user: return gen(CODES.LOGIN_REQUIRED) favor_tool = FavorTool(favor_cache, user.id) ids = favor_tool.get_favors_received(start_num, count) type_ids = defaultdict(list) for obj_id, _type in ids: type_ids[_type].append(obj_id) favor_objs_func = { FAVOROBJECT.DIARY: DiaryFavor.list_by_ids, FAVOROBJECT.TOPIC: ProblemFavor.list_by_ids, FAVOROBJECT.TRACTATE: TractateFavorService.list_by_ids, FAVOROBJECT.QUESTION: QaFavorServices.question_get_valid_favor, FAVOROBJECT.ANSWER: QaFavorServices.answer_get_valid_favor, } objs_func = { FAVOROBJECT.DIARY: list_diaries_by_favor_ids, FAVOROBJECT.TOPIC: list_topics_by_favor_ids, FAVOROBJECT.TRACTATE: list_tractates_by_favor_ids, FAVOROBJECT.QUESTION: list_question_by_favor_ids, FAVOROBJECT.ANSWER: list_answer_by_favor_ids, } # 获取对应的数据方法 favor_objs = defaultdict(list) # 收藏记录 entries = defaultdict(dict) # 收藏的对象 for _type, _ids in type_ids.items(): get_favor_objs_func = favor_objs_func.get(_type) if get_favor_objs_func: fvors = get_favor_objs_func(_ids) favor_objs[_type] = fvors items = objs_func.get(_type)(fvors) entries[_type] = items result = [] user_ids = [] for _type, objs in favor_objs.items(): for obj in objs: user_ids.append(obj.user_id) favor_time = None if hasattr(obj, "update_time"): favor_time = obj.update_time.timestamp() elif hasattr(obj, "created_time"): favor_time = obj.created_time.timestamp() elif hasattr(obj, "create_time"): favor_time = obj.create_time.timestamp() info = { 'vote_id': obj.id, 'type': _type, 'user_id': obj.user_id, 'favor_time': favor_time, } if _type == FAVOROBJECT.DIARY: diary = entries.get(_type, {}).get(obj.diary_id) info["content"] = diary.title if diary else "" info["id"] = obj.diary_id elif _type == FAVOROBJECT.TOPIC: topic = entries.get(_type, {}).get(obj.problem_id) info["content"] = topic.answer if topic else "" info["id"] = obj.problem_id elif _type == FAVOROBJECT.TRACTATE: tractate = entries.get(_type, {}).get(obj.tractate_id) info["content"] = tractate.content if tractate else "" info["id"] = obj.tractate_id elif _type == FAVOROBJECT.QUESTION: question = entries.get(_type, {}).get(obj.question_id) info["content"] = question.content if question else "" info["id"] = obj.question_id elif _type == FAVOROBJECT.ANSWER: answer = entries.get(_type, {}).get(obj.answer_id) info["content"] = answer.content if answer else "" info["id"] = obj.answer_id result.append(info) users = UserConvertService.get_user_info_by_user_ids(user_ids) for item in result: user = users.get(item["user_id"]) if not user: continue item.update({ "user_info": user, # 以下是冗余字段 "user_id": user.get("user_id", 0), "nickname": user.get("user_name", ""), "portrait": user.get("portrait", ""), "membership_level": user.get("membership_level", "0"), }) # 根据初始顺序进行排序 result.sort(key=lambda item: ids.index((str(item.get("vote_id")), item.get("type")))) return result @bind('mimas/favor/received_aggregation') def get_reseived_favor_aggregation(): No_new_favor = { 'is_about_me': False, 'toptitle': '', 'type': NotificationType.VOTE_FAVOR, 'unread_count': 0, "title": u'收藏', "url": "", "content": "", "create_time": "", "user": "", "is_view": False, "imgheader": settings.NOTIFICATION_VOTE_IMG, "pic": "", "id": '', } user = get_current_user() if not user: return No_new_favor favor_tool = FavorTool(favor_cache, user.id) count = get_user_unread_favor_count(user.id) if count == 0: return No_new_favor # get latest favor user info: prevent cache id can not find favor item, try 3 times else: favor = None for r in favor_tool.get_favors_received(0, 3): _id, _type = r if _type == FAVOROBJECT.DIARY: try: favor = DiaryFavor.objects.get(pk=_id) user = UserService.get_user_by_user_id(favor.user_id) return format_result( user, count, create_time=get_timestamp_or_none(favor.created_time)) except DiaryFavor.DoesNotExist: continue if _type == FAVOROBJECT.TOPIC: try: favor = ProblemFavor.objects.get(pk=_id) user = UserService.get_user_by_user_id(favor.user_id) return format_result( user, count, create_time=get_timestamp_or_none(favor.created_time)) except ProblemFavor.DoesNotExist: continue if _type == FAVOROBJECT.TRACTATE: from talos.models.tractate.favor import TractateFavor try: favor = TractateFavor.objects.get(pk=_id) user = UserService.get_user_by_user_id(favor.user_id) return format_result( user, count, create_time=get_timestamp_or_none(favor.update_time)) except TractateFavor.DoesNotExist: continue if not favor: No_new_favor['unread_count'] = count return No_new_favor def format_result(latest_user_info, count, create_time=None): nickname = latest_user_info.nickname portrait = latest_user_info.portrait title = '{}等人给你点了赞'.format(nickname) if count > 1 else '{}赞了你'.format(nickname) return { 'is_about_me': False, 'toptitle': '', 'type': NotificationType.VOTE_ME, 'unread_count': count, "title": title, "url": "", "content": "", "create_time": create_time, "user": "", "is_view": False, "imgheader": portrait, "pic": "", "id": '', }