Esempio n. 1
0
class Event(document.Document):
    meta = {'allow_inheritance': True}
    name = orm.StringField(required=True)
    city = orm.StringField(required=True)
    slug = orm.StringField(required=True, unique=True)
    location = orm.StringField(required=True)
    address = orm.StringField(required=True)
    image = orm.URLField()

    start_date = orm.DateTimeField(required=True)
    end_date = orm.DateTimeField(required=True)
    registration_end = orm.DateTimeField(required=True)

    price = orm.IntField(default=0)

    schedule = orm.SortedListField(orm.EmbeddedDocumentField(ScheduleItem),
                                   ordering='time')

    @classmethod
    def find_event(cls, id):
        try:
            oid = ObjectId(id)
        except:
            return Event.objects(slug=id).first()

        return Event.objects(id=oid).first()
Esempio n. 2
0
class Template(me.Document):
    name = me.StringField(max_length=100, required=True)
    desc = me.StringField(max_length=300)
    input = me.BooleanField(default=False)
    output = me.BooleanField(default=True)
    forward = me.BooleanField(default=False)
    rules = me.SortedListField(me.ReferenceField('Rule'))

    def __repr__(self):
        return "Template <%s>" % self.name
Esempio n. 3
0
class Alarm(db.Document):
    meta = {
        'strict': False,
        'queryset_class': fm.BaseQuerySet,
        'index_opts': INDEX_OPTS,
        'index_background': INDEX_BACKGROUND,
        'index_cls': INDEX_CLS,
        'auto_create_index': AUTO_CREATE_INDEX,
        'indexes': ['owner']
    }

    class Event(_Event):
        pass

    owner = db.ReferenceField(User, required=True, reverse_delete_rule=db.CASCADE, unique=True)
    records = db.SortedListField(db.EmbeddedDocumentField(AlarmRecord), ordering="created_at", reverse=True)

    @classmethod
    def create_alarm(cls,
                     event=None,
                     user_from=None,
                     user_to=None,
                     conversation=None,
                     post=None,
                     comment=None,
                     request=None,
                     message=None):

        current_time_stamp = pendulum.now().int_timestamp

        if not user_to or not user_from:
            raise Exception("Both user_from and user_to are required values.")

        alarm = Alarm.objects(owner=user_to).first()
        if not alarm:
            alarm = Alarm(owner=user_to).save()

        push = AlarmRecord(
            event=event,
            user_id=user_from.id,
            post_id=post.id if post else None,
            comment_id=comment.id if comment else None,
            request_id=request.id if request else None,
            conversation_id=conversation.id if conversation else None,
            message=message,
            created_at=current_time_stamp
        )

        alarm.records = alarm.records[:199]  # max 200
        alarm.records.append(push)
        alarm.save()

        return alarm
Esempio n. 4
0
class Host(me.Document):

    FIELDS = ('name', 'htype')

    TYPES = ((0, 'PC/Laptop'), (1, 'Server'), (2, 'Firewall'), (3, 'Other'))

    name = me.StringField(max_length=100, required=True)
    htype = me.IntField(choices=TYPES, default=0)
    interfaces = me.ListField(me.EmbeddedDocumentField(Interface))
    template = me.ReferenceField(Template)
    rules = me.SortedListField(me.ReferenceField('Rule'))

    def __repr__(self):
        return "Host <%s>" % self.name
Esempio n. 5
0
class Conversation(db.Document):
    meta = {
        'strict': False,
        'queryset_class': fm.BaseQuerySet,
        'index_opts': INDEX_OPTS,
        'index_background': INDEX_BACKGROUND,
        'index_cls': INDEX_CLS,
        'auto_create_index': AUTO_CREATE_INDEX,
        'indexes': ['participants']
    }
    title = db.StringField(max_length=500)
    participants = db.SortedListField(db.ReferenceField(User), reverse_delete_rule=db.CASCADE)
    references = db.ListField(db.ReferenceField(User), reverse_delete_rule=db.CASCADE)
    messages = db.EmbeddedDocumentListField(EmbeddedMessage)
    created_at = db.LongField(required=True)
    available = db.BooleanField(required=True, default=False)
    available_at = db.LongField()
Esempio n. 6
0
class Anime(mongoengine.Document):
    title = mongoengine.EmbeddedDocumentField(Title, required=True)
    hidden = mongoengine.BooleanField(required=True, default=False)
    description = mongoengine.StringField(required=True, default=None)
    subtitles = mongoengine.ListField(mongoengine.ReferenceField("User"))
    voiceover = mongoengine.ListField(mongoengine.ReferenceField("User"))
    teams = mongoengine.ListField(mongoengine.ReferenceField("Team"))
    created = mongoengine.DateTimeField(default=datetime.now)
    year = mongoengine.IntField(default=datetime.now().year)
    slug = mongoengine.StringField(required=True)
    poster = mongoengine.ReferenceField("File")
    banner = mongoengine.ReferenceField("File")
    views = mongoengine.IntField(default=0)

    genres = mongoengine.ListField(
        mongoengine.ReferenceField("Descriptor", reverse_delete_rule=4))
    franchises = mongoengine.ListField(
        mongoengine.ReferenceField("Descriptor", reverse_delete_rule=4))
    category = mongoengine.ReferenceField("Descriptor",
                                          reverse_delete_rule=4,
                                          required=True)
    state = mongoengine.ReferenceField("Descriptor",
                                       reverse_delete_rule=4,
                                       required=True)

    aliases = mongoengine.ListField(mongoengine.StringField())
    rating = mongoengine.DecimalField(default=0)
    search = mongoengine.StringField()

    episodes = mongoengine.SortedListField(
        mongoengine.EmbeddedDocumentField(Episode), ordering="position")

    meta = {
        "alias":
        "default",
        "collection":
        "anime",
        "indexes": [
            "slug",
            "genres",
            "category",
            "state",
            "title.jp",
            "title.ua",
            "search",
            "rating",
        ]
    }

    def dict(self, episodes=False):
        print()
        data = {
            "description": self.description,
            "title": self.title.dict(),
            "category": self.category.dict(),
            "rating": float(self.rating),
            "state": self.state.dict(),
            "slug": self.slug,
            "year": self.year,
            "poster": None,
            "banner": None,
            "subtitles": [],
            "voiceover": [],
            "genres": [],
            "franchises": [],
            "teams": []
        }

        for account in self.subtitles:
            data["subtitles"].append(account.dict())

        for account in self.voiceover:
            data["voiceover"].append(account.dict())

        for genre in self.genres:
            data["genres"].append(genre.dict())

        for franchise in self.franchises:
            data["franchises"].append(franchise.dict())

        for team in self.teams:
            data["teams"].append(team.dict())

        if self.poster is not None:
            if self.poster.uploaded is True:
                data["poster"] = self.poster.link()

        if self.banner is not None:
            if self.poster.uploaded is True:
                data["banner"] = self.banner.link()

        if episodes:
            data["episodes"] = []

            for episode in self.episodes:
                data["episodes"].append(episode.dict())

        return data
Esempio n. 7
0
class User(db.Document):
    meta = {
        'strict': False,
        'queryset_class': fm.BaseQuerySet,
        'index_opts': INDEX_OPTS,
        'index_background': INDEX_BACKGROUND,
        'index_cls': INDEX_CLS,
        'auto_create_index': AUTO_CREATE_INDEX,
        'indexes': [
            # 'uid',
            # 'phone',
            # '-last_login_at',
            # (("location", "2dsphere"), '-birthed_at'),
            # (("location", "2dsphere"), '-birthed_at', '-star_rating_avg'),
        ]
    }

    class Status(object):
        OPENED = "OPENED"
        PENDING = "PENDING"
        APPROVED = "APPROVED"
        REJECTED = "REJECTED"
        BLOCKED = "BLOCKED"
        UNREGISTERED = "UNREGISTERED"

    uid = db.StringField()
    nickname = db.StringField()
    sex = db.StringField(choices=["M", "F"])
    birthed_at = db.LongField()
    height = db.IntField()
    body_id = db.IntField()
    occupation = db.StringField()
    education = db.StringField()
    religion_id = db.IntField()
    drink_id = db.IntField()
    smoking_id = db.IntField()
    blood_id = db.IntField()
    device_token = db.StringField()
    location = db.PointField()
    introduction = db.StringField()
    joined_at = db.LongField()
    last_login_at = db.LongField()
    job = db.StringField()
    area = db.StringField()
    phone = db.StringField(unique=True)

    user_images = db.SortedListField(db.EmbeddedDocumentField(UserImage), ordering="index")
    user_images_temp = db.SortedListField(db.EmbeddedDocumentField(UserImage), ordering="index")

    charm_ids = db.ListField(db.IntField())
    ideal_type_ids = db.ListField(db.IntField())
    interest_ids = db.ListField(db.IntField())

    available = db.BooleanField(default=False)
    status = db.StringField(choices=[
        Status.OPENED,
        Status.PENDING,
        Status.APPROVED,
        Status.REJECTED,
        Status.BLOCKED,
        Status.UNREGISTERED
    ])
    star_rating_avg = db.FloatField(default=0)

    free_pass_tokens = db.ListField(db.LongField(), default=[0, 0])
    free_open_tokens = db.ListField(db.LongField(), default=[0])

    is_phones_cached = False
    phones_cache = []

    def identify(self, request):
        uid = request.headers.get("uid", None)
        if self.uid != uid:
            raise abort(401)

    def list_posts(self) -> list:
        result = Post.list_posts(author=self.id, is_deleted=False)
        return result

    def list_requests_to_me(self, response=None):
        return Request.list_requests(user_to=self, response=response)

    def list_requests_from_me(self, response=None):
        return Request.list_requests(user_from=self, response=response)

    def list_conversations(self):
        return Conversation.objects(participants=self).all()

    def list_users_rated_me(self):
        star_ratings = StarRating.objects(user_to=self).order_by("-rated_at").as_pymongo()
        score_repository = {
            str(s.get("user_from")): dict(score=s.get("score", 0), rated_at=s.get("rated_at")) for s in star_ratings
        }
        raters = User.list(id__in=score_repository.keys()).as_pymongo()

        result = []
        for rater in raters:
            user_id = str(rater.get("_id"))
            o = score_repository.get(user_id)
            o["user"] = rater
            result.append(o)

        return result

    def list_users_rated_me_high(self):
        star_ratings = StarRating.objects(user_to=self, score__gte=4).order_by("-rated_at").as_pymongo()
        user_ids = [star_rating.get("user_from", None) for star_rating in star_ratings]
        users_dict = User.get_users_dict(set(user_ids))
        result = [users_dict.get(str(user_id)) for user_id in user_ids]
        return filter(lambda x: x, result)

    def list_users_i_rated_high(self):
        star_ratings = StarRating.objects(user_from=self, score__gte=4).order_by("-rated_at").as_pymongo()
        user_ids = [star_rating.get("user_to", None) for star_rating in star_ratings]
        users_dict = User.get_users_dict(set(user_ids))
        result = [users_dict.get(str(user_id)) for user_id in user_ids]
        return filter(lambda x: x, result)

    def get_recommendation(self):
        recommendation = Recommendation.objects(owner=self).first()
        if not recommendation:
            recommendation = Recommendation(
                owner=self, user_ids=[], last_recommended_at=pendulum.yesterday().int_timestamp
            )
            recommendation.save()
            recommendation.reload()
        return recommendation

    def get_first_image(self):
        return self.user_images[0].url if self.user_images else ""

    def remove_user_from_recommendation(self, user_to_remove):
        if not user_to_remove:
            raise ValueError("owner and target must be required value.")
        recommendation = Recommendation.objects(owner=self).first()
        if not recommendation:
            return
        for index, rec_user_id in enumerate(recommendation.user_ids):
            if rec_user_id == user_to_remove.id:
                del recommendation.user_ids[index]
                break
        recommendation.save()

    def get_current_amount_of_point(self):
        payments = Payment.objects(owner=self).all()
        amount_sum = 0
        for payment in payments:
            amount_sum += payment.amount
        return amount_sum

    def is_available_for_free_pass_token(self):
        token_min = min(self.free_pass_tokens)
        current_time = pendulum.now().int_timestamp
        delta = current_time - token_min
        return delta >= 0

    def consume_free_pass_token(self):
        tokens = list(self.free_pass_tokens)
        index = tokens.index(min(tokens))
        tokens[index] = pendulum.now().int_timestamp + FREE_PASS_NEXT * 60 * 60
        if len(tokens) != 2:
            tokens = [0, 0]
        self.update(free_pass_tokens=tokens)

    def is_available_for_free_open_token(self):
        token_min = min(self.free_open_tokens)
        current_time = pendulum.now().int_timestamp
        delta = current_time - token_min
        return delta >= 0

    def consume_free_open_token(self):
        tokens = list(self.free_open_tokens)
        index = tokens.index(min(tokens))
        tokens[index] = pendulum.now().int_timestamp + FREE_OPEN_NEXT * 60 * 60
        if len(tokens) != 1:
            tokens = [0]
        self.update(free_open_tokens=tokens)

    def consume(self, amount):
        if amount <= 0:
            raise ValueError("Illegal amount found. The amount must be bigger than 0.")

        total_amount = self.get_current_amount_of_point()
        if total_amount < amount:
            raise Exception(
                "Not enough balance..\n"
                "remaining amount: {total_amount}, amount to consume: {amount}".format(
                    total_amount=total_amount, amount=amount))

        Payment(
            owner=self,
            type="CONSUME",
            amount=(amount * -1),
            created_at=pendulum.now().int_timestamp
        ).save()

    def purchase(self,
                 platform=None,
                 order_id=None,
                 product_id=None,
                 amount=None,
                 created_at=None,
                 purchase_time_ms=None):

        if not product_id or amount <= 0 or not order_id or not created_at or not purchase_time_ms or not platform:
            raise ValueError("Illegal amount found. The amount must be bigger than 0.")

        existing = Payment.objects(order_id=order_id, purchase_time_ms=purchase_time_ms).first()
        if existing:
            return Payment.Result.DUPLICATE

        payment = Payment(
            owner=self,
            type="PURCHASE",
            platform=platform,
            order_id=order_id,
            product_id=product_id,
            amount=amount,
            created_at=int(created_at),
            purchase_time_ms=int(purchase_time_ms)
        )
        payment.save()

        return Payment.Result.PURCHASED

    def list_payments(self, to_json=False):
        if not to_json:
            return Payment.objects(owner=self).all()
        else:
            payments = Payment.objects(owner=self).as_pymongo()
            return list(payments)

    def set_contact(self, phones):
        contact = self.get_contact()
        contact.phones = phones
        contact.last_updated = pendulum.now().int_timestamp
        contact.save()
        contact.reload()
        return contact

    def add_user_knows_me(self, user):
        contact = self.get_contact()
        user_ids_know_me = contact.user_ids_know_me
        if user.id not in user_ids_know_me:
            contact.user_ids_know_me.append(user.id)
            contact.save()

    def get_contact(self):
        contact = Contact.objects(owner=self).first()
        if not contact:
            contact = Contact(
                owner=self,
                phones=[],
                last_updated_at=pendulum.now().int_timestamp)
            contact.save()
            contact.reload()
        return contact

    def get_phones(self):
        if self.is_phones_cached:
            return self.phones_cache
        contact = self.get_contact()
        self.phones_cache = contact.phones
        self.is_phones_cached = True
        return self.phones_cache

    def has_in_contacts(self, phone) -> bool:
        if not phone:
            return False
        phones = self.get_phones()
        return phone in phones

    def does_know_each_other(self, user):
        if self.has_in_contacts(user.phone):  # checks whether I know him
            return True
        if user.has_in_contacts(self.phone):  # checks whether he knows me
            return True
        return False

    def _get_nin_ids(self) -> set:

        app.logger.debug("collecting nin ids..")
        nin_ids = set()
        # nin with requests
        requests_to_me = Request.objects(user_to=self).as_pymongo()
        requests_from_me = Request.objects(user_from=self).as_pymongo()
        to_me_ids = [r["user_from"] for r in requests_to_me]
        from_me_ids = [r["user_to"] for r in requests_from_me]
        nin_ids.update(to_me_ids)
        nin_ids.update(from_me_ids)

        app.logger.debug("collected nin ids with requests..")

        # nin with recommendation
        recommendation = self.get_recommendation()
        recommendation = recommendation.to_mongo()
        rec_ids = [user_id for user_id in recommendation["user_ids"]]
        nin_ids.update(rec_ids)

        app.logger.debug("collected nin ids with recommendation..")

        # nin with contact
        contact = self.get_contact()
        know_ids = [user_id for user_id in contact.user_ids_know_me]
        nin_ids.update(know_ids)
        phones = contact.phones
        ids_in_contacts = User.list_only_user_ids(phone__in=phones)
        nin_ids.update(ids_in_contacts)

        app.logger.debug("collected nin ids with contacts phone numbers..")

        return nin_ids

    def list_recommended_user_ids(self, nin_ids: set = None, result=None,
                                  min_diameter=0, max_diameter=30,
                                  star_rating_avg=3.5):
        """Generates recommended users. If not found, recursively try it increasing diameter up to 300 km."""
        sex = next((s for s in ['M', 'F'] if s != self.sex))
        result = result or []
        nin_ids = nin_ids or self._get_nin_ids()

        location = self.location["coordinates"] if self.location else [127.0977517240413, 37.49880740259655]
        params = dict(
            location__near=location,
            location__min_distance=min_diameter * 1000,
            location__max_distance=max_diameter * 1000,
            birthed_at__gte=self.birthed_at - (12 * ONE_YEAR_TO_SECONDS),
            birthed_at__lte=self.birthed_at + (12 * ONE_YEAR_TO_SECONDS),
            star_rating_avg__gte=star_rating_avg,
            id__nin=nin_ids,
            available=True,
            sex=sex
        )

        if max_diameter > 300:
            return result

        app.logger.debug("collecting users with params: {0}..".format(str(params)))

        cursor = User.list(**params)

        index = 0
        while True:
            app.logger.debug("cursor is moving..")
            user = _get_index_at(cursor, index)

            if user is None:
                break

            if self.does_know_each_other(user):
                self.add_user_knows_me(user)
                user.add_user_knows_me(self)
                nin_ids.add(user.id)
                continue
            result.append(user.id)
            index += 1
            if len(result) >= 2:
                break

        if len(result) < 2:
            app.logger.debug("Not enough recommended user found.. collecting more")
            return self.list_recommended_user_ids(
                nin_ids, result=result, star_rating_avg=star_rating_avg * 0.9,
                min_diameter=max_diameter, max_diameter=max_diameter * 2)

        return result  # 126.98265075683594, 37.56100082397461

    def list_realtime_user_ids(self):
        nin_ids = self._get_nin_ids()
        sex = 'M' if self.sex == 'F' else 'F'
        last_login_at_gte = pendulum.now().int_timestamp - (60 * 30)
        params = dict(
            last_login_at__gte=last_login_at_gte,
            id__nin=nin_ids,
            sex=sex,
            available=True
        )

        cursor = User.objects(**params).order_by("-last_login_at")
        size = cursor.count()

        result = []
        for index in range(0, size):
            user = cursor[index]
            if self.does_know_each_other(user):
                self.add_user_knows_me(user)
                user.add_user_knows_me(self)
                continue
            result.append(user.id)
            if len(result) >= 10:
                break
        return result

    @time_lapse
    def list_user_ids_within_distance(self, distance=5):
        nin_ids = self._get_nin_ids()
        sex = 'M' if self.sex == 'F' else 'F'

        location = self.location["coordinates"] if self.location else [127.0936859, 37.505808]
        params = dict(
            location__near=location,
            location__max_distance=distance * 1000,  # 1000 = 1 km
            location__min_distance=0 * 1000,
            birthed_at__gte=self.birthed_at - (12 * ONE_YEAR_TO_SECONDS),
            birthed_at__lte=self.birthed_at + (12 * ONE_YEAR_TO_SECONDS),
            id__nin=nin_ids,
            sex=sex,
            available=True
        )

        user_ids = User.list_only_user_ids(**params)
        random.seed(_get_hash(str(self.id)) + 1)
        random.shuffle(user_ids)

        result = []
        for user_id in user_ids:
            user = User.get(id=user_id)
            if self.does_know_each_other(user):
                self.add_user_knows_me(user)
                user.add_user_knows_me(self)
                continue
            result.append(user.id)
            if len(result) >= 10:
                break

        return result

    @classmethod
    def excludes(cls):
        return [
            "uid",
            "joined_at",
            "user_images_temp",
            "free_pass_tokens",
            "free_open_tokens",
            "phone"
        ]

    @classmethod
    def get(cls, **kwargs):
        excludes = kwargs.get("excludes", User.excludes())
        return User.objects.exclude(*excludes).get_or_404(**kwargs)

    @classmethod
    def list(cls, **kwargs):
        users = User.objects(**kwargs).exclude(*User.excludes())
        return users

    @classmethod
    def get_users_dict(cls, user_ids: set):
        users = User.list(id__in=list(user_ids)).as_pymongo()
        return {str(user.get("_id")): user for user in users}

    @classmethod
    def get_verified_user(cls, user_id, request):
        uid = request.headers.get("uid", None)
        user = User.get(uid=uid)
        if user_id != str(user.id):
            abort(401)
        return user

    @classmethod
    @time_lapse
    def list_only_user_ids(cls, **kwargs):
        query = User.objects(**kwargs).only("id").as_pymongo()
        return [o["_id"] for o in query]

    def is_admin(self):
        admin = Admin.objects(user=self).first()
        return admin is not None

    def withdraw(self):
        unregister = Unregister(nickname=self.nickname, uid=self.uid, phone=self.phone, user=self)
        unregister.save()

        self.uid = None
        self.phone = None
        self.device_token = None
        self.user_images = []
        self.user_images_temp = []
        self.available = False
        self.status = User.Status.REJECTED
        self.nickname = "탈퇴 한 회원"
        self.save()

        Post.objects(author=self).delete()
        # Comment.objects(owner=user).delete()
        # Request.objects(user_from=user).delete()
        # Request.objects(user_to=user).delete()
        # StarRating.objects(user_from=user).delete()
        # StarRating.objects(user_to=user).delete()
        # Contact.objects(owner=user).delete()
        # Alarm.objects(owner=user).delete()

    def get_setting(self):
        setting = Setting.objects(owner=self).first()
        if not setting:
            setting = Setting(owner=self)
            setting.save()
            setting.reload()
        return setting