class ArticleAdminOperateLog(Document): article_id = StringField() operator_id = StringField() operate_type = IntField() operate_at = DateTimeField() operator_email = StringField() media_id = StringField() limit_post_times = IntField() @classmethod def generate_log(cls, request, article_id, operate_type, media_id=None, limit_post_times=None): now = datetime.datetime.utcnow() if media_id: media_id = str(media_id) ArticleAdminOperateLog.objects.create( article_id=article_id, operator_id=str(request.user.id), operate_type=operate_type, operate_at=now, operator_email=request.user.email, media_id=media_id, limit_post_times=limit_post_times)
class Announcement(Document): title = StringField() content = StringField() published_at = DateTimeField() modified_at = DateTimeField() user_id = StringField() user_email = StringField() status = IntField() type = IntField()
class DailyMpArticleBenefit(Document): date = StringField() lang = StringField() online_seq_id = IntField() category = StringField() site_url = StringField() uclick = StringField() share_percent = FloatField() revenue_rate = FloatField() unit_price = FloatField() revenue = FloatField() checking_status = IntField()
class DailyMpBenefit(Document): lang = StringField() date = StringField() site_url = StringField() revenue = FloatField() checked_revenue = FloatField() checking_status = IntField()
class Notification(Document): media_id = StringField() status = IntField() content = StringField() type = IntField() published_at = DateTimeField() @classmethod def create_notification(cls, media_id, n_type, content): now = datetime.datetime.utcnow() notification = cls.objects.create(status=STATUS_UNREAD, type=n_type, content=content, media_id=media_id, published_at=now) return notification
class Bonus(Document): amount = FloatField() type = IntField() reason = StringField() create_at = DateTimeField() operator_id = StringField() operator_email = StringField() media_id = StringField()
class CommentMediaInfo(Document): media_id = StringField() media_title = StringField() sync_time = DateTimeField() unread_comment_count = IntField() usable = BooleanField() synced_langs = ListField(StringField()) last_comment_tag_mapping = DictField()
class Article(Document): media_id = StringField() title = StringField() content = StringField() top_images = ListField(DictField()) related_images = ListField(DictField()) youtube_video_ids = ListField(StringField()) online_url = StringField() online_seq_id = IntField() cover_type = IntField() words_count = IntField() status = IntField() category = StringField() keywords = ListField(StringField()) language = StringField() published_at = DateTimeField() last_modified_at = DateTimeField() submited_at = DateTimeField() takedown_at = DateTimeField() deleted_at = DateTimeField() last_op_at = DateTimeField() checked_at = DateTimeField() checker_email = StringField() checker = StringField() check_reason = StringField() check_reason_type = IntField() submit_times = IntField() revision = BooleanField() porn_score = IntField() @property def source_url(self): return 'mpa_%s' % str(self.id) def get_media(self): m = getattr(self, '_media', None) if m: return m from media.models import MediaAccount m = MediaAccount.objects.with_id(self.media_id) self._media = m return m def gen_online_url(self): if not self.online_url: return None domain = LANG_DOMAIN_MAPPING.get(self.language) if not domain: domain = 'newsdog.today' return 'http://%s%s' % (domain, self.online_url) def check_reached_submit_limit(self): return self.submit_times >= ARTICLE_SUBMIT_LIMIT
class WithDraw(Document): user_id = StringField() media_id = StringField() amount = FloatField() payment_info = DictField() create_at = DateTimeField() status = IntField() operator_id = StringField() operator_email = StringField() operate_at = DateTimeField()
class DailyArticle(Document): date = StringField() online_seq_id = IntField() lang = StringField() rec_count = IntField() read_count = IntField() uclick_count = IntField() # user unique read count share_count = IntField() comment_count = IntField() favorite_count = IntField()
class RealTimeArticle(Document): online_seq_id = IntField() lang = StringField() rec_count = IntField() read_count = IntField() share_count = IntField() comment_count = IntField() favorite_count = IntField()
class MediaAdminOperateLog(Document): media_id = StringField() operator_id = StringField() operate_type = IntField() operate_at = DateTimeField() operate_content = StringField() operator_email = StringField() @classmethod def generate_log(cls, request, media_id, operate_type, operate_content): now = datetime.datetime.utcnow() MediaAdminOperateLog.objects.create(media_id=media_id, operator_id=str(request.user.id), operate_type=operate_type, operate_at=now, operate_content=operate_content, operator_email=request.user.email)
class Image(Document): media_id = StringField() # image_type = StringField() width = IntField() height = IntField() origin = StringField() thumb = StringField() thumb_width = IntField() thumb_height = IntField() headline = StringField() headline_width = IntField() headline_height = IntField() usable = BooleanField() source = StringField() type = StringField() thumb_jpg = StringField() origin_jpg = StringField() headline_jpg = StringField()
class MediaPromotionUser(Document): media_id = StringField() media_join_at = DateTimeField() banned_at = StringField() status = IntField() promotion_code = StringField() time_reached = BooleanField() read_reached = BooleanField() no_banned = BooleanField() @classmethod def gen_pcode(cls): pcode = None for x in xrange(3): code = cls.gen_promotion_code() mpc = cls.objects(promotion_code=code).first() if mpc: continue pcode = code break return pcode @classmethod def gen_promotion_code(cls): chars = [] for x in xrange(6): chars.append(random.choice(PROMOTION_CODE_CAND)) return ''.join(chars) @classmethod def gen_promotion_user(cls, media_id): now = datetime.datetime.utcnow() pcode = cls.gen_pcode() mpu = cls.objects.create(media_id=media_id, media_join_at=now, status=MEDIA_PROMOTION_NEWBIE_STATUS, promotion_code=pcode, time_reached=False, read_reached=False, no_banned=True) return mpu def banned_promotion_user(self): if self.status == MEDIA_PROMOTION_NORMAL_STATUS: media = MediaAccount.objects.with_id(self.media_id) notify_utils.create_media_promotion_notification( media, MEDIA_PROMOTION_NOTIFICATION_BANNED_TYPE) self.status = MEDIA_PROMOTION_BANNED_STATUS now = str(datetime.datetime.utcnow().date()) self.banned_at = now self.no_banned = False self.save() mpls = MediaPromotionLog.objects(get_bonus=False, father_media_id=self.media_id) mpls.update(set__is_banned=True, set__modified_at=now) def judge_to_normal(self): return self.time_reached and self.read_reached and self.no_banned @classmethod def get_pcode_owner_media(cls, pcode): mpu = cls.objects(promotion_code=pcode).first() if not mpu: raise MediaPcodeNotExist if mpu.status != MEDIA_PROMOTION_NORMAL_STATUS: raise MediaPcodeNotAllowable return mpu
class DailyMedia(Document): lang = StringField() date = StringField() rec_count = IntField() read_count = IntField() uclick_count = IntField() share_count = IntField() comment_count = IntField() mp_fans_count = IntField() new_count = IntField() site_url = StringField() live_article_count = IntField() extra_rec_count = IntField() extra_read_count = IntField() extra_uclick_count = IntField()
class RealTimeMedia(Document): lang = StringField() site_url = StringField() follow_count = IntField() read_count = IntField()
class MediaAccount(Document): verified_status = IntField() info_update = BooleanField() lang_synced_status_mapping = DictField() title = StringField() unformatted_title = StringField() description = StringField() icon = StringField() new_title = StringField() new_description = StringField() new_icon = StringField() user_id = StringField() user_pan_no = StringField() user_real_name = StringField() user_email = StringField() user_phone = StringField() user_location_address = StringField() user_location_city = StringField() user_location_state = StringField() user_pin_code = StringField() last_modified_at = DateTimeField() checked_at = DateTimeField() updated_at = DateTimeField() create_at = DateTimeField() checker_email = StringField() updated_email = StringField() check_reason = StringField() valid_duration = IntField() share_percent = IntField() total_revenue = FloatField() revenue_update_date = StringField() total_withdraw = FloatField() payment_info = DictField() daily_submit_limit = IntField() limit_end_at = DateTimeField() limit_reason = StringField() suspend_reason = StringField() # NOTE: india time zone grade = IntField() remark = StringField() is_internship = BooleanField() @classmethod def check_pan_no_reach_limit(cls, user_pan_no): count = cls.objects(user_pan_no=user_pan_no).count() if count >= 3: return True return False @classmethod def check_pan_no_is_black(cls, user_pan_no): black_pan_no = PancardBlackList.objects(user_pan_no=user_pan_no) return bool(black_pan_no) def withdraw_stat(self): total_revenue, total_withdraw, total_balance = MediaAccount.calc_balance( self.total_revenue or 0, self.total_withdraw or 0) return dict(total_revenue=('%.2f' % total_revenue), total_withdraw=('%.2f' % total_withdraw), total_balance=('%.2f' % total_balance)) @classmethod def calc_balance(cls, revenue, withdraw): def decimal_floor(num): # 小数向下取整函数 ret = (math.floor(num * 100)) / 100.0 if ret > num: # 避免极端情况,产生的数据错误 return ret - 0.01 return ret def decimal_ceil(num): # 小数向上取整函数 ret = (math.ceil(num * 100)) / 100.0 if ret < num: return ret + 0.01 return ret if revenue - withdraw > 1: # 在两个数距离较大的时候,被减数向下取整,减数向上取整 _revenue = decimal_floor(revenue) _withdraw = decimal_floor(withdraw) if _withdraw != withdraw: # 避免withdraw为零的时候,出现0.01的情况,造成用户感知明显 _withdraw += 0.01 else: # 在两个数距离较小时,被减数和减数都向下取整,避免减数大于被减数的情况出现 _revenue = decimal_floor(revenue) _withdraw = int(withdraw * 100) / 100.0 _balance = (_revenue - _withdraw) return _revenue, _withdraw, decimal_floor(_balance) def can_auto_pass(self): if self.grade == MEDIA_GRADE_A: return not 5 == random.randint(0, 9) if self.grade == MEDIA_GRADE_P: return not 1 == random.randint(0, 1) return False def judge_pass_internship(self): pass_article_count = Article.objects(media_id=str(self.id), status=STATUS_PUBLISHED).count() return pass_article_count >= (MEDIA_INTERNSHIP_ARTICLE_NUM - 1) def limit_media(self, request, limit_days, daily_limit, limit_reason): limit_end_time = time_utils.get_india_now() + datetime.timedelta( int(limit_days)) self.limit_end_at = datetime.datetime(limit_end_time.year, limit_end_time.month, limit_end_time.day) self.limit_reason = limit_reason self.daily_submit_limit = daily_limit self.save() notify_utils.create_media_limit_notification(self) content = MEDIA_AMDIN_OPERATE_LIMIT_POST_CONTENT_TEMPL % (daily_limit, limit_days) MediaAdminOperateLog.generate_log(request, str(self.id), MEDIA_AMDIN_OPERATE_TYPE_LIMIT_POST, content) mpu = MediaPromotionUser.objects(media_id=str(self.id)).first() mpu.banned_promotion_user() @property def verify_passed(self): return self.verified_status == VERIFY_STATUS_PASSED @property def verify_failed(self): return self.verified_status == VERIFY_STATUS_FAILED @property def verify_submitted(self): return self.verified_status == VERIFY_STATUS_SUBMITTED @property def verify_suspend(self): return self.verified_status == VERIFY_STATUS_SUSPEND @property def site_url(self): return media_utils.gen_site_url(self.id) @classmethod def gen_unformatted_title(cls, title): unformatted_title = title.strip().lower() return MULTI_SPACES_PATTERN.sub(' ', unformatted_title) def add_submit_log(self, article_id): try: MediaSubmitArticleLog.objects.create( media_id=str(self.id), article_id=article_id, date=str(time_utils.get_india_now().date())) except NotUniqueError: return @property def is_under_limit(self): if not self.limit_end_at: return False now = time_utils.get_india_now() if now > self.limit_end_at: return False return True @property def under_limit_date(self): if not self.is_under_limit: return if not self.limit_end_at: return None return self.limit_end_at.strftime('%Y-%m-%d %H:%M') def check_reached_submit_limit(self): if not self.is_under_limit: return False daily_submit_count = MediaSubmitArticleLog.objects( media_id=str(self.id), date=str(time_utils.get_india_now().date())).count() return daily_submit_count >= self.daily_submit_limit def check_internship_submit_limit(self, article_id=None): if not self.is_internship: return False if article_id: article_submit_count = MediaSubmitArticleLog.objects( media_id=str(self.id), article_id=str(article_id)).count() if article_submit_count > 0: return False daily_submit_count = MediaSubmitArticleLog.objects( media_id=str(self.id), date=str(time_utils.get_india_now().date())).count() return daily_submit_count >= self.daily_submit_limit def withdraw_in_processing(self): count = WithDraw.objects(media_id=str(self.id), status=WD_STATUS_SUMBMITTED).count() return not count == 0 def has_paytm(self): return self.payment_info and 'paytm_account' in self.payment_info