event_handler.py 9.58 KB
import datetime

from user_hierarchy.models import UserEventLog
from ..tasks import process_push_message, process_notify_message, process_user_add_value


class LIMITTYPE:

    UPPER = 'upper'
    LOWER = 'lower'


class EventHandler(object):
    __slots__ = ('event_type', 'trigger_time', 'user_id', 'item_id', 'pre_payment')

    _is_push = False
    push_message = ''

    _is_notify = False
    notify_message = ''

    time_limit = {
        # 合记次数限制  修改日记本评分次数
        'upper_or_lower': None,  # upper/lower,
        'limit_time': None,
    }

    daily_timi_limit = {
        # 单日限制   日记本评分跨度记录
        'upper_or_lower': None,  # upper/lower,
        'limit_time': None,
    }

    value = None
    daily_max_value_limit = 300

    def __init__(self, event_type, trigger_time, user_id, item_id, pre_payment):
        self.event_type = event_type

        if trigger_time:
            trigger_time = datetime.datetime.fromtimestamp(trigger_time)
        else:
            trigger_time = datetime.datetime.now()

        self.trigger_time = trigger_time
        self.user_id = user_id
        self.item_id = item_id
        self.pre_payment = pre_payment

    def process(self):
        """process event by limit
            return value
        """
        self._pre_process()
        result = self.check_limit()
        return self._process_result(result)

    def _pre_process(self):
        pass

    def check_limit(self):
        if self.time_limit['limit_time'] and not self._check_time_limit():
            return 0

        if self.daily_timi_limit['limit_time'] and not self._check_daily_time_limit():
            return 0

        if not self._check_extra_limit():
            return 0

        return self._check_daily_max_value_limit()

    def _check_time_limit(self):
        count = UserEventLog.objects.filter(
            user_id=self.user_id,
            event_type=self.event_type,
            related_item_id=self.item_id
        ).count()

        if self.time_limit['upper_or_lower'] == LIMITTYPE.UPPER and count >= self.time_limit['limit_time']:
            return False

        elif self.time_limit['upper_or_lower'] == LIMITTYPE.LOWER and count < self.time_limit['limit_time']:
            return False

        return True

    def _check_daily_time_limit(self):
        count = UserEventLog.objects.filter(
            user_id=self.user_id,
            event_type=self.event_type,
            trigger_time__date=datetime.date.today(),
        ).count()

        if self.daily_timi_limit['upper_or_lower'] == LIMITTYPE.UPPER and count >= self.daily_timi_limit['limit_time']:
            return False

        elif self.daily_timi_limit['upper_or_lower'] == LIMITTYPE.LOWER and count < self.daily_timi_limit['limit_time']:
            return False

        return True

    def _check_daily_max_value_limit(self):
        today_value = UserEventLog.get_user_today_value(self.user_id)
        if today_value >= self.daily_max_value_limit:
            return 0

        today_last_value = self.daily_max_value_limit - today_value
        if today_last_value >= self.value:
            return self.value

        return today_last_value

    def _check_extra_limit(self):
        return True

    def _process_result(self, result):
        # record event log
        # process push
        # trigger update user level
        UserEventLog.objects.create(
            event_type=self.event_type,
            related_item_id=self.item_id,
            trigger_time=self.trigger_time,
            value=result,
            user_id=self.user_id,
        )

        if self._is_push:
            self._push_message(result)

        if self._is_notify:
            return self._build_notify_message(result)

        if result != 0:
            self._process_user_add_value()

        return result

    def _push_message(self, result):
        process_push_message.delay(user_id=self.user_id, message=self.push_message.format(result))

    def _build_notify_message(self, result):
        process_notify_message.delay(user_id=self.user_id, message=self.notify_message.format(result))

    def _process_user_add_value(self):
        process_user_add_value.delay(self.user_id)


class BindPhoneEventHandler(EventHandler):
    time_limit = {
        # 合记次数限制
        'upper_or_lower': LIMITTYPE.UPPER,  # upper/lower,
        'limit_time': 1,
    }
    value = 20


class CompletePortraitEventHandler(EventHandler):
    time_limit = {
        # 合记次数限制
        'upper_or_lower': LIMITTYPE.UPPER,  # upper/lower,
        'limit_time': 1,
    }
    value = 10


class CreateOpTopicEventHandler(EventHandler):
    toast_message = '+{}成长值'
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 3,
    }
    value = 50


class CreateNonOpTopicEventHandler(EventHandler):
    toast_message = '+{}成长值'
    # daily_timi_limit = {
    #     # 单日限制
    #     'upper_or_lower': LIMITTYPE.UPPER,
    #     'limit_time': 3,
    # }
    value = 30


class DiaryCommentedEventHandler(EventHandler):
    """NOTE: not in use."""

    time_limit = {
        # 合记次数限制
        'upper_or_lower': LIMITTYPE.LOWER,
        'limit_time': 50,
    }
    value_timi_limit = {
        # 加分次数限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 1,
    }
    value = 5

    def _check_extra_limit(self):
        # 只加一次分
        count = UserEventLog.objects.filter(
            user_id=self.user_id,
            event_type=self.event_type,
            related_item_id=self.item_id
        ).exclude(value=0).count()
        if count >= self.value_timi_limit['limit_time']:
            return False

        return True


class TopicCommentedEventHandler(EventHandler):
    """NOTE: not in use."""

    time_limit = {
        # 合记次数限制
        'upper_or_lower': LIMITTYPE.LOWER,
        'limit_time': 50,
    }
    value_timi_limit = {
        # 加分次数限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 1,
    }
    value = 5

    def _check_extra_limit(self):
        # 只加一次分
        count = UserEventLog.objects.filter(
            user_id=self.user_id,
            event_type=self.event_type,
            related_item_id=self.item_id
        ).exclude(value=0).count()
        if count >= self.value_timi_limit['limit_time']:
            return False

        return True


class OpDiaryBeExFromFine(EventHandler):
    """手术类 良 变为 优."""
    # _is_push = True
    # push_message = '{}'
    value = 20


class OpDiaryBeExFromOther(EventHandler):
    """手术类 非良 变为 优."""
    # _is_push = True
    # push_message = '{}'
    value = 50


class OpDiaryEeFineFromOther(EventHandler):
    """手术类 非优 变为 良."""
    # _is_push = True
    # push_message = '{}'
    value = 30


class OpDiaryBeFineFromEx(EventHandler):
    """手术类 从 优 变为 良."""
    value = -20


class NonOpDiaryBeExFromFine(EventHandler):
    """非手术类 从 良 变为 优."""
    value = 20


class NonOpDiaryBeExFromOther(EventHandler):
    """非手术类 从 非良 变为 优."""
    value = 30


class NonOpDiaryBeFineFromOther(EventHandler):
    """非手术类 从 非优 变为 良."""
    #_is_push = True
    #push_message = '{}'
    value = 10


class NonOpDiaryBeFineFromEx(EventHandler):
    """非手术类 从 优 变为 良."""
    value = -20


class CommentDiary(EventHandler):
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 10,
    }
    value = 5


class CommentTopic(EventHandler):
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 10,
    }
    value = 5


class AnswerRecommended(EventHandler):
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 5,
    }
    value = 30


class QuestionRecommended(EventHandler):
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': LIMITTYPE.UPPER,
        'limit_time': 5,
    }
    value = 30


class TopicIsSpam(EventHandler):
    value = -50


class CommentIsSpam(EventHandler):
    value = -50


class BuyService(EventHandler):
    lower_payment = 200

    def _check_extra_limit(self):
        if self.pre_payment >= self.lower_payment:
            self.value = self.pre_payment
            return True

        return False


class CheckinHandler(EventHandler):
    daily_timi_limit = {
        # 单日限制
        'upper_or_lower': 'upper',  # upper/lower,
        'limit_time': 1,
    }

    def _check_extra_limit(self):
        value_list = [2, 5, 5, 2, 2]
        current_month = datetime.date.today().month
        days = UserEventLog.objects.filter(
            user_id=self.user_id,
            event_type=self.event_type,
            trigger_time__month=current_month,
        ).values_list('trigger_time', flat=True)
        days = [d.day for d in days]
        sustain_count = _get_sustain_checkin_counts(days)

        self.value = value_list[sustain_count % 5]
        return True


class CommentHandler(EventHandler):
    '''评论日记本/日记贴/回答/专栏, 替换旧的评论 added 7.6.20'''
    value = 5


class CommentMultiHandler(EventHandler):
    '''累计评论日记本/日记贴/回答/专栏 added 7.6.20'''
    value = 20


def _get_sustain_checkin_counts(checkin_days):
    current_day = datetime.date.today().day
    days = [(lambda i: 1 if i in checkin_days else 0)(i) for i in range(current_day)]
    _sum = 0

    for i in reversed(days):
        if i == 1:
            _sum += 1
        else:
            break

    return _sum