# coding=utf-8 from __future__ import absolute_import, print_function, unicode_literals import random import datetime from datetime import timedelta from celery import shared_task from gm_types.gaia import CONST_STRINGS as const_strings from gm_types.push.enum import AUTOMATED_PUSH from gm_types.mimas import NOTICATION_LIST_CATEGORY from gm_types.push import PUSH_INFO_TYPE from six.moves import xrange from gm_protocol import GmProtocol from qa.utils.statistic import get_async_args_v2 from talos.cache.base import diary_pv_cache from talos.models.diary import Diary from talos.models.diary import DiaryVote from talos.models.topic import TopicVote from talos.services.user import UserService from utils.protocol import gm_protocol from utils.push import vote_push, push_task_to_user_multi from utils.rpc import rpc_client from .tasks import view_increase, view_increase_amount from ..models.topic import Problem from talos.cache.base import fake_vote_cache from talos.tools.vote_tool import VoteTool from talos.cache.base import vote_cache from talos.manager.diary import diary_list_manager from communal.tasks import intelligent_push_task from talos.services.other import get_user_lastest_device_app_version_by_user_id from utils.common import is_version_gray _MAX_SLEEP_PERSON = 5000 def get_fake_view_num(start, end): return random.randint(start, end) def get_sleep_user(repeat_times): user_ids = rpc_client['api/user/get_sleep_user'](number=repeat_times).unwrap() return user_ids def normal_vote(user, item, is_diary=False, incr_range=[5, 15]): """ :param user: 点赞的用户 :param item: 日记本或者日记贴 :param is_diary: 是否日记本 :param incr_range: 浏览量增加的范围 :return: """ if is_diary: diary = item like_num = diary.like_num # 增加点赞数 diary.like_num += 1 diary.save() # 增加浏览量 fake_view_num = get_fake_view_num(*incr_range) diary_pv_cache.incrby(str(diary.id), fake_view_num) # 点赞推送 日记本点赞进入防干扰 alert = u'有1位朋友给你点了赞,快来看看吧>>' push_url = GmProtocol().get_diary_detail(id=diary.id) version = get_user_lastest_device_app_version_by_user_id(diary.user_id) # 推送跳转到消息页的赞列表 if is_version_gray(version, '7.29.0'): push_url = GmProtocol().vote_or_favor_list( segment_index=NOTICATION_LIST_CATEGORY.VOTE, new_vote=True, ) intelligent_push_task.delay( content_id=diary.id, user_ids=[diary.user_id], push_type=AUTOMATED_PUSH.DIARY_RECEIVED_PRAISE, platform=None, extra={ 'type': PUSH_INFO_TYPE.GM_PROTOCOL, 'pushUrl': push_url, 'push_url': push_url, }, alert=alert, others={ "title": "@{} 给你点了赞".format(user.nick_name), "alert": alert, }, labels={}, ) else: topic = item # 增加点赞数 view_increase(Problem.get_redis_vote_key(), topic.id) if topic.diary_id: # 增加对应的日记点赞数 view_increase(Diary.get_redis_diary_topic_vote_key(), topic.diary_id) # 增加浏览量 view_increase_amount(const_strings.TOPIC_VIEW, topic.id, get_fake_view_num(*incr_range)) #topic.diary.operation_time 手术时间 topic.operation_date if not topic.diary or not topic.diary.operation_time or not topic.operation_date: return end, start = topic.operation_date, topic.diary.operation_time days = (end.replace(hour=0, minute=0, second=0, microsecond=0) - start.replace(hour=0, minute=0, second=0, microsecond=0)).days diary_title = u'{diary_title}(第{days}天)'.format(diary_title=topic.diary.title, days=days) alert = u'{user_name}刚刚赞了你的《{diary_title}》,比心~'.format(user_name=str(user.nick_name), diary_title=diary_title) push_url = GmProtocol().get_topic_detail(id=topic.id) user_id = topic.user_id version = get_user_lastest_device_app_version_by_user_id(user_id) # 推送跳转到消息页的赞列表 if is_version_gray(version, '7.29.0'): push_url = GmProtocol().vote_or_favor_list( segment_index=NOTICATION_LIST_CATEGORY.VOTE, new_vote=True, ) vote_push(user_id=user_id, alert=alert, push_type=AUTOMATED_PUSH.DIARY_POST_RECEIVED_PRAISE, push_url=push_url) @shared_task def fake_vote(repeat_times, item_id, need_view_increase=True, incr_range=[1, 1], is_topic=True, force_push=False, author_name=None, topic_title=None): """ Get random {amount} users who's last login time earlier than 2015,and let them vote for topic each person one time :param repeat_times: :param topic: :param need_view_increase :param incr_num 增加多少浏览数 :param is_topic :return: """ # 获取沉睡用户 user_extras = get_sleep_user(repeat_times) if is_topic: return fake_vote_topic(user_extras, item_id, need_view_increase, incr_range, force_push, author_name, topic_title) return fake_vote_diary(user_extras, item_id, need_view_increase, incr_range, force_push) def fake_vote_diary(users, diary_id, need_view_increase=True, incr_range=[1, 1], force_push=False): diary = Diary.objects.get(pk=diary_id) # 帖子下线, 不处理 if not diary.is_online: return diary_fake_vote_key = "diary_fake_vote_{id}".format(id=diary_id) is_set = fake_vote_cache.set(diary_fake_vote_key, 1, nx=True, ex=30) if not is_set: return cnt, u_nick_name = 0, '' for ue in users: _, created = DiaryVote.objects.get_or_create(user_id=ue, diary_id=diary.id, is_fake=True) if created: # 对日记本作者增加点赞数 u = UserService.get_user_by_user_id(diary.user_id) u.incr_vote_count() if not u_nick_name: vote_user = UserService.get_user_by_user_id(ue) u_nick_name = vote_user.nickname cnt += 1 if not need_view_increase: return # 增加可视点赞数 like_num = diary.like_num before_fake = like_num diary.like_num += cnt diary.save() after_fake = diary.like_num view_num = 0 # 每个点赞增加随机浏览量 for i in xrange(cnt): view_num += random.randint(*incr_range) # 增加可视浏览数 diary_pv_cache.incrby(str(diary.id), view_num) if force_push: alert = u'{user_name} 刚刚感谢了你的《{diary_title}》,比心~'.format(user_name=u_nick_name, diary_title=diary.title) push_url = GmProtocol().get_diary_detail(id=diary.id) vote_push(diary.user_id, alert=alert, push_type=AUTOMATED_PUSH.DIARY_RECEIVED_PRAISE, push_url=push_url) def fake_vote_topic(userids, topic_id, need_view_increase=True, incr_range=[1, 1], force_push=False, author_name=None, topic_title=None): # reload data from db now_date = datetime.datetime.now() if not 9 <= now_date.hour < 22: # 超过晚十点灌水任务不执行 return topic_fake_vote_key = "topic_fake_vote_{id}".format(id=topic_id) is_set = fake_vote_cache.set(topic_fake_vote_key, 1, nx=True, ex=30) if not is_set: return topic = Problem.objects.get(pk=topic_id) if not topic.is_online: return cnt, u_nick_name = 0, '' # 增加可视的点赞数 before_fake = topic.vote_amount view_increase_amount(const_strings.TOPIC_VOTE, topic.id, cnt) after_fake = topic.vote_amount for ue in userids: if topic.is_offline: continue topic_vote, created = TopicVote.objects.get_or_create( user_id=ue, topic_id=topic.id, is_fake=True, topic_author_id=topic.user_id, ) if created: # 对日记作者增加点赞数 u = UserService.get_user_by_user_id(topic.user_id) u.incr_vote_count() if not u_nick_name: vote_user = UserService.get_user_by_user_id(ue) u_nick_name = vote_user.nickname cnt += 1 view_increase(Problem.get_redis_vote_key(), topic.id) if need_push(before_fake, after_fake, force_push=force_push): view_increase(Problem.get_redis_vote_key(), topic.id) alert = u'{user_name}刚刚赞了你的《{diary_title}》,比心~'.format( user_name=u_nick_name, diary_title=topic.diary.title) push_url = GmProtocol().get_topic_detail(id=topic_id) vote_push(user_id=topic.user_id, alert=alert, is_force=force_push, push_url=push_url, push_type=AUTOMATED_PUSH.DIARY_POST_RECEIVED_PRAISE) if not need_view_increase: return # 为每个点赞数增加可视浏览数 for i in xrange(cnt): fake_view_topic(topic.id, incr_range) @shared_task def fake_view_topic(topic_id, incr_range=[1, 1]): """ 增加帖子浏览量 :param topic: :return: """ incr_num = get_fake_view_num(*incr_range) view_increase_amount(const_strings.TOPIC_VIEW, topic_id, incr_num) def need_push(before, after, force_push=False): # 放大后点赞数超整10, 或者不满十个赞但需要强制推送 before = int(before) after = int(after) return (after / 10 - before / 10) >= 1 or (after < 10 and force_push) def process_topic_vote_for_create(topic_id): """ 处理创建日记贴之后的点赞和增加浏览量 :param topic: :return: """ # 异步增加点赞数和浏览量 # 规则1, 发帖[30s, 60s], 增加浏览量 countdown, incr_range = get_async_args_v2(const_strings.TOPIC_VOTE_RULE1) fake_view_topic.apply_async(args=(topic_id,), kwargs={'incr_range': incr_range}, countdown=countdown[0]) countdowns, incr_range = get_async_args_v2(const_strings.CREATE_TOPIC_VOTE) for index, cd in enumerate(countdowns): task_info = fake_vote.apply_async(args=(1, topic_id), kwargs={'incr_range': incr_range, 'force_push': True}, countdown=cd ) from talos.logger import qiniu_logger qiniu_logger.info("task_id====={task_id}".format(task_id=task_info.task_id)) @shared_task def diary_push_timing(): # 灌水1.0上线 下线所有之前的灌水逻辑 return