import datetime import random from gm_types.gaia import DIARY_CONTENT_LEVEL from gm_types.mimas import VOTE_TASK_TYPE, TRACTATE_CONTENT_LEVEL from qa.utils.statistic import get_countdown from talos.cache.base import fake_vote_cache from talos.logger import info_logger from talos.services import UserConvertService from talos.tasks.tractate import tractate_fake_vote from talos.tasks.vote import fake_vote def format_timestamp(_datetime, hour=0, minute=0, second=0): return int(_datetime.replace(hour=hour, minute=minute, second=second).timestamp()) class FakeVoteEvent(object): # http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=27100295 # 第一部分任务: # 达人、医生、机构 有效时间段内,10 minute - 2 hour 任务执行次数(不在9-22时间段内不灌水) first_repeat_times = 6 first_normal_user = 5 #第二部分任务:任务执行次数取值区间 # 达人、医生、机构 second_repeat_times = { DIARY_CONTENT_LEVEL.GENERAL: [9, 14], DIARY_CONTENT_LEVEL.BETTER: [19, 24], DIARY_CONTENT_LEVEL.FINE: [24, 29], DIARY_CONTENT_LEVEL.EXCELLENT: [29, 39], } # 普通用户 second_repeat_times_normal_user = { DIARY_CONTENT_LEVEL.GENERAL: [0, 0], DIARY_CONTENT_LEVEL.BETTER: [0, 1], DIARY_CONTENT_LEVEL.FINE: [1, 3], DIARY_CONTENT_LEVEL.EXCELLENT: [5, 10], } # 任务执行次数(一天一次,从第二天开始,记为1) SECOND_DAY = 1, THIRD_DAY = 2, FOURTH_DAY = 3, FIFTH_DAY = 4, SIXTH_DAY = 5, SEVENTH_DAY = 6, # 普通用户 灌水次数控制, 从第二天开始(审核等级不同,灌水次数不同,在这里统一管理),共七天 """ 第x天: { 一般:灌水执行次数区间, 较好:灌水执行次数区间, 良好:灌水执行次数区间, 优秀:灌水执行次数区间, } """ REPEAT_TIMES_RANGE = { FakeVoteEvent.SECOND_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [2, 4], # ('3', u'一般') DIARY_CONTENT_LEVEL.BETTER: [4, 5], # ('3.5', u'较好') DIARY_CONTENT_LEVEL.FINE: [5, 6], # ('4', u'良好') DIARY_CONTENT_LEVEL.EXCELLENT: [8, 10], # ('5', u'优秀') }, FakeVoteEvent.THIRD_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [2, 3], DIARY_CONTENT_LEVEL.BETTER: [3, 4], DIARY_CONTENT_LEVEL.FINE: [4, 5], DIARY_CONTENT_LEVEL.EXCELLENT: [6, 8], }, FakeVoteEvent.FOURTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 2], DIARY_CONTENT_LEVEL.BETTER: [2, 3], DIARY_CONTENT_LEVEL.FINE: [3, 4], DIARY_CONTENT_LEVEL.EXCELLENT: [4, 6], }, FakeVoteEvent.FIFTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 1], DIARY_CONTENT_LEVEL.BETTER: [1, 2], DIARY_CONTENT_LEVEL.FINE: [2, 3], DIARY_CONTENT_LEVEL.EXCELLENT: [2, 4], }, FakeVoteEvent.SIXTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 1], DIARY_CONTENT_LEVEL.BETTER: [1, 1], DIARY_CONTENT_LEVEL.FINE: [1, 2], DIARY_CONTENT_LEVEL.EXCELLENT: [1, 2], }, FakeVoteEvent.SEVENTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 1], DIARY_CONTENT_LEVEL.BETTER: [1, 1], DIARY_CONTENT_LEVEL.FINE: [1, 2], DIARY_CONTENT_LEVEL.EXCELLENT: [1, 2], }, } # 达人、机构 灌水次数控制 SU_REPEAT_TIMES_RANGE = { FakeVoteEvent.SECOND_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [10, 15], DIARY_CONTENT_LEVEL.BETTER: [20, 25], DIARY_CONTENT_LEVEL.FINE: [25, 30], DIARY_CONTENT_LEVEL.EXCELLENT: [30, 35], }, FakeVoteEvent.THIRD_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [8, 10], DIARY_CONTENT_LEVEL.BETTER: [15, 20], DIARY_CONTENT_LEVEL.FINE: [20, 25], DIARY_CONTENT_LEVEL.EXCELLENT: [25, 30], }, FakeVoteEvent.FOURTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [6, 8], DIARY_CONTENT_LEVEL.BETTER: [5, 10], DIARY_CONTENT_LEVEL.FINE: [15, 20], DIARY_CONTENT_LEVEL.EXCELLENT: [20, 25], }, FakeVoteEvent.FIFTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [4, 5], DIARY_CONTENT_LEVEL.BETTER: [3, 5], DIARY_CONTENT_LEVEL.FINE: [10, 15], DIARY_CONTENT_LEVEL.EXCELLENT: [15, 20], }, FakeVoteEvent.SIXTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 3], DIARY_CONTENT_LEVEL.BETTER: [4, 5], DIARY_CONTENT_LEVEL.FINE: [5, 10], DIARY_CONTENT_LEVEL.EXCELLENT: [10, 15], }, FakeVoteEvent.SEVENTH_DAY: { DIARY_CONTENT_LEVEL.GENERAL: [1, 2], DIARY_CONTENT_LEVEL.BETTER: [2, 4], DIARY_CONTENT_LEVEL.FINE: [1, 5], DIARY_CONTENT_LEVEL.EXCELLENT: [5, 10], }, } class VoteTaskTool(object): def __init__(self, task_type, cache_client=fake_vote_cache): self.cache_cli = cache_client self.task_type = task_type if self.task_type == VOTE_TASK_TYPE.TRACTATE: self.key = 'tr_fake_vote_cache' elif self.task_type == VOTE_TASK_TYPE.DIARY: self.key = 'd_fake_vote_cache' elif self.task_type == VOTE_TASK_TYPE.TOPIC: self.key = 't_fake_vote_cache' elif self.task_type == VOTE_TASK_TYPE.QUESTION: self.key = 'q_fake_vote_cache' def get_repeat_times(self, business_id): """ 获取任务执行了几次(一天一次) :return: """ if self.cache_cli.exist(self.key): repeat_times = int(self.cache_cli.hget(self.key, business_id)) return repeat_times return 0 def update_repeat_times(self, business_id): """ 每次执行完灌水任务,计数+1 :param business_id: :return: """ self.cache_cli.hincrby(self.key, int(business_id)) def cache_key(self, business_id): """ 初次触发灌水完成后,入缓存。 :param business_id: :return: """ self.cache_cli.hset(self.key, int(business_id), 1) # today = datetime.datetime.today() # 过期时间 到第八天的凌晨0点 # self.cache_cli.expire( # self.key, # (today.replace(hour=0, minute=0, second=0) - today).seconds + 6*24*2600 # ) def check_key_is_valid(self, business_id): """ 检查key是否还在有效期内(1-7天) :param business_id: :return: """ operate_times = self.cache_cli.hget(self.key, int(business_id)) if operate_times: # 1 <= days <= 6 is valid if int(operate_times) > 6: info_logger.info( '{}:{}, 点赞灌水任务完成'.format( VOTE_TASK_TYPE.getDesc(key=self.task_type), business_id, )) self.cache_cli.hdel(self.key, int(business_id)) return False return True else: return False def get_all_valid_tasks(self): all_tasks = self.cache_cli.hgetall(self.key) info_logger.info('all_tasks:{}'.format(all_tasks)) return all_tasks def del_cache_key(self, business_id): self.cache_cli.hdel(self.key, business_id) def time_valid_check(now_date): if 9 <= now_date.hour < 22: return True return False def is_special_user(user_id): """ 判断用户的身份(两类): 1、(医生,机构,达人用户) 2、普通用户 :param user_id: :return: """ user_info = UserConvertService.get_user_info_by_user_id(user_id, simple=True) membership_level = int(user_info.get('membership_level', 0)) doctor_id = user_info.get('doctor_id', None) hospital_id = user_info.get('hospital_id', None) if any([membership_level, doctor_id, hospital_id]): return True else: return False def need_push(): """  是否需要push通知 20% :return: """ if random.randint(0, 10) < 2: return True return False def fake_vote_v1(task_type, business_id, special_user, content_level): """ 第一天的点赞任务单独处理 :param task_type: 任务类型 帖子,日记本,日记帖,问题... :param business_id: 帖子... id :param special_user: 是不是特殊类型用户(医生,机构,达人用户) :param content_level: 审核等级 :return: """ # 第一天任务, 分两部分处理 # 第一部分:如果发帖时间在有效时间段内,灌6/5条点赞记录,不在有效时间段内不灌水,剩余的在第二部分处理 now_date = datetime.datetime.now() is_valid_time = time_valid_check(now_date) if not is_valid_time: # 不在9-22时间段内, 第一天任务不执行,从第二天开始 fake_vote_tool = VoteTaskTool(cache_client=fake_vote_cache, task_type=task_type) fake_vote_tool.cache_key(business_id) return first_repeat_times = FakeVoteEvent.first_repeat_times if special_user else FakeVoteEvent.first_normal_user cds = get_countdown(first_repeat_times, time_range=(10*60, 2*60*60)) if task_type == VOTE_TASK_TYPE.TRACTATE: for index, cd in enumerate(cds): if is_valid_time and index <= 3: force_push = True else: force_push = need_push() result = tractate_fake_vote.apply_async( args=(1, business_id), kwargs={'incr_range': [3, 11], "force_push": force_push}, countdown=cd ) info_logger.info( "帖子点赞第一批任务,id:{}, task_id:{},开始执行时间:{}".format( business_id, result.task_id, now_date+datetime.timedelta(seconds=cd) ) ) info_logger.info("帖子点赞第一批任务完成,id:{}, 任务个数:{}".format(business_id, len(cds))) elif task_type == VOTE_TASK_TYPE.TOPIC: for index, cd in enumerate(cds): if is_valid_time and index <= 3: force_push = True else: force_push = need_push() result = fake_vote.apply_async( args=(1, business_id), kwargs={'incr_range': [2, 20], 'force_push': force_push}, countdown=cd ) info_logger.info( "日记帖点赞第一批任务,id:{}, task_id:{},开始执行时间:{}".format( business_id, result.task_id, now_date + datetime.timedelta(seconds=cd) ) ) info_logger.info("日记帖点赞第一批任务完成,id:{}, 任务个数:{}".format(business_id, len(cds))) # 第二部分任务: two_hours_later = now_date + datetime.timedelta(hours=2) # 如果两小时以后时间仍然在当天9-20点之间,就将第一天灌水任务执行完, 否则不执行 if 9 <= two_hours_later.hour < 22 and now_date.day == two_hours_later.day: start_time = int(two_hours_later.timestamp()) end_time = format_timestamp(now_date, hour=2) + 24*60*60 else: # 第一天任务完成 记录到缓存 fake_vote_tool = VoteTaskTool(cache_client=fake_vote_cache, task_type=task_type) fake_vote_tool.cache_key(business_id) return # elif two_hours_later.hour < 9: # 当天9点之前,延迟到九点开始 # start_time = format_timestamp(now_date, hour=9) # end_time = format_timestamp(now_date, hour=22) # # else: # 当天20点之后,延迟到第二天九点开始 # start_time = format_timestamp(now_date, hour=9) + 24*60*60 # end_time = format_timestamp(now_date, hour=22) + 24*60*60 # 第二部分的任务剩余量: if special_user: repeat_range = FakeVoteEvent.second_repeat_times.get(str(content_level), [0, 0]) second_repeat_times = random.randint( repeat_range[0], repeat_range[1] ) else: repeat_range = FakeVoteEvent.second_repeat_times_normal_user.get(str(content_level), [0, 0]) second_repeat_times = random.randint( repeat_range[0], repeat_range[1] ) time_range = (start_time, end_time) cds = get_countdown(second_repeat_times, time_range=time_range) if task_type == VOTE_TASK_TYPE.TRACTATE: for cd in cds: force_push = need_push() result = tractate_fake_vote.apply_async( args=(1, business_id), kwargs={'incr_range': [3, 11], "force_push": force_push}, eta=datetime.datetime.fromtimestamp(cd - 8*3600) ) info_logger.info( "帖子点赞第二批任务,id:{}, task_id:{},开始执行时间:{}".format( business_id, result.task_id, datetime.datetime.fromtimestamp(cd) ) ) info_logger.info("帖子点赞第二批任务完成,id:{}, 任务个数:{}".format(business_id, len(cds))) elif task_type == VOTE_TASK_TYPE.TOPIC: for cd in cds: force_push = need_push() result = fake_vote.apply_async( args=(1, business_id), kwargs={'incr_range': [2, 20], 'force_push': force_push}, eta=datetime.datetime.fromtimestamp(cd - 8 * 3600) ) info_logger.info( "日记帖点赞第二批任务,id:{}, task_id:{},开始执行时间:{}".format( business_id, result.task_id, datetime.datetime.fromtimestamp(cd) ) ) info_logger.info("日记帖点赞第二批任务完成,id:{}, 任务个数:{}".format(business_id, len(cds))) # 第一天任务完成 记录到缓存 fake_vote_tool = VoteTaskTool(cache_client=fake_vote_cache, task_type=task_type) fake_vote_tool.cache_key(business_id)