Example #1
0
File: user.py Project: matoous/newz
    def subscribe(self, feed: "Feed"):
        """
        Subscribe user to given feed
        :param feed: feed to subscribe
        :return:
        """
        if self.feed_subs >= MAX_SUBSCRIPTIONS_FREE:
            return False

        # if user is banned from feed he can't subscribe
        if Ban.by_user_and_feed(self, feed) is not None:
            return False

        # save subscription
        db.table("feeds_users").insert(user_id=self.id, feed_id=feed.id)
        key = "subs:{}".format(self.id)
        ids = cache.get(key) or []
        ids.append(feed.id)
        cache.set(key, ids)

        self.incr("feed_subs", 1)
        self.update_with_cache()

        # TODO DO IN QUEUE
        feed.incr("subscribers_count", 1)
        return True
Example #2
0
File: feed.py Project: matoous/newz
    def by_slug(cls, slug: str) -> Optional["Feed"]:
        """
        Get feed by slug
        :param username: slug
        :return:
        """
        cache_key = "fslug:{}".format(slug)

        # check feed slug cache
        in_cache = cache.get(cache_key, raw=True)
        uid = int(in_cache) if in_cache else None

        # return user on success
        if uid is not None:
            return Feed.by_id(uid)

        # try to load user from DB on failure
        feed = Feed.where("slug", slug).first()

        # cache the result
        if feed is not None:
            cache.set(cache_key, feed.id, raw=True)
            feed.write_to_cache()

        return feed
Example #3
0
    def update(self, comments: ["Comment"]):
        """
        Update sorted comments in cache
        This should be called on votes (maybe not all of them) and on new comments
        :param link_id: link id
        :param comment: comment
        """
        for comment in comments:
            cache_key = self._cache_key(comment.parent_id)
            lock_key = self._lock_key(comment.parent_id)

            # update comment under read - write - modify lock
            with Lock(cache.conn, lock_key):
                # maybe check against the comment tree to see if it is missing or it just is not initialized yet
                comments = (
                    cache.get(cache_key) or []
                )  # so maybe load comments instead of []

                # update comment
                for i in range(len(comments)):
                    if comments[i][0] == comment.id:
                        comments[i] = [
                            comment.id,
                            confidence(comment.ups, comment.downs),
                        ]
                        break
                else:
                    # add comment
                    comments.append(
                        [comment.id, confidence(comment.ups, comment.downs)]
                    )

                # sort and save
                comments = sorted(comments, key=lambda x: x[1:], reverse=True)
                cache.set(cache_key, comments)
Example #4
0
File: user.py Project: matoous/newz
    def by_username(cls, username: str) -> Optional["User"]:
        """
        Get user by username
        :param username: username
        :return:
        """
        cache_key = "uname:{}".format(username)

        # check username cache
        in_cache = cache.get(cache_key, raw=True)
        uid = int(in_cache) if in_cache else None

        # return user on success
        if uid is not None:
            return User.by_id(uid)

        # try to load user from DB on failure
        u = User.where("username", username).first()

        # cache the result
        if u is not None:
            cache.set(cache_key, u.id, raw=True)
            u.write_to_cache()

        return u
Example #5
0
 def write_to_cache(self):
     """
     Write self to cache
     What should and what shouldn't be written can be modified by
     __hidden__ attribute on class (more in documentation of orator)
     """
     # save token to redis for limited time
     cache.set(self._cache_key, self.serialize())
Example #6
0
File: user.py Project: matoous/newz
 def subscribed_feed_ids(self) -> List[str]:
     """
     Get users subscribed feed ids
     :return: list of ids
     """
     key = "subs:{}".format(self.id)
     ids = cache.get(key)
     if ids is None:
         ids = [feed.id for feed in self.feeds]
         cache.set(key, ids)
     return ids
Example #7
0
 def add(self, comments: ["Comment"]):
     """
     Adds comment to comment tree for given link
     :param link: link
     :param comment: comment
     """
     with Lock(cache.conn, self._lock_key):
         tree = self.load_tree()
         for comment in comments:
             tree.setdefault(comment.parent_id, []).append(comment.id)
         cache.set(self._cache_key, tree)
Example #8
0
 def remove(self, comments: ["Comment"]):
     """
     Remove comments from comment tree
     :param comments: comments
     """
     with Lock(cache.conn, self._lock_key):
         tree = self.load_tree()
         for comment in comments:
             tree[comment.parent_id] = [
                 id for id in tree[comment.parent_id] if id != comment.id
             ]
         cache.set(self._cache_key, tree)
Example #9
0
File: user.py Project: matoous/newz
    def unsubscribe(self, feed: "Feed"):
        db.table("feeds_users").where("user_id", "=",
                                      self.id).where("feed_id", "=",
                                                     feed.id).delete()
        self.decr("feed_subs", 1)

        # TODO DO IN QUEUE
        feed.decr("subscribers_count", 1)
        key = "subs:{}".format(self.id)
        ids = cache.get(key)
        if ids is not None:
            ids = [id for id in ids if id != feed.id]
            cache.set(key, ids)
        return True
Example #10
0
    def by_slug(cls, slug) -> Optional["Link"]:
        """
        Get link by slug
        :param slug: slug
        :return: maybe link
        """
        cache_key = "lslug:{}".format(slug)
        id = cache.get(cache_key)
        if id is None:
            link = Link.where("slug", slug).first()
            if link is not None:
                id = link.id
                cache.set(cache_key, id)

        return Link.by_id(id) if id else None
Example #11
0
    def create(self):
        """
        Creates email verification which expires after given time
        and sends email to user to verify his email
        """

        # create token
        self.token = token_urlsafe(16)

        # save token to redis for limited time
        cache.set(self._cache_key, self.user.id, ttl=PASSWORD_RESET_EXPIRE, raw=True)

        # send email with verification link
        msg = reset_email(self.user, self._url)
        q.enqueue(JOB_send_mail, msg, result_ttl=0)
Example #12
0
    def login(self, remember_me: bool = False):
        """
        Login the user
        Generate access token which gets saved in session, info about user is then saved to redis
        :param remember_me:
        """
        token = DisposableToken.get()
        self._accessor_cache["session_token"] = token.id
        session_key = "us:{}".format(self.session_token)
        cache.set(session_key, self.id, ttl=0 if remember_me else 60 * 60 * 2, raw=True)
        login_user(self, remember=remember_me)

        LinkVote.by_user_and_vote_type(self.id, UPVOTE)
        LinkVote.by_user_and_vote_type(self.id, DOWNVOTE)
        CommentVote.by_user_and_vote_type(self.id, UPVOTE)
        CommentVote.by_user_and_vote_type(self.id, DOWNVOTE)
Example #13
0
 def load_tree(self) -> dict:
     """
     Load the tree
     :return: tree
     """
     tree = cache.get(self._cache_key)
     if not tree:
         comments = (
             Comment.where("link_id", self.link_id).select("parent_id", "id").get()
             or []
         )
         tree = {}
         for comment in comments:
             tree.setdefault(comment.parent_id, []).append(comment.id)
         cache.set(self._cache_key, tree)
     self._tree = tree
     return tree
Example #14
0
    def build_tree(self):
        """
        Build sorted tree of comments for given comment_id
        If comment_id is None, tree for whole link is build
        :param comment_id: comment_id for comment, None for link
        :return: (comment_id, [sorted subtrees])
        """
        # load all comments that will be needed
        comment_ids = self._tree.ids()
        comments = (
            {comment.id: comment for comment in Comment.by_ids(comment_ids)}
            if comment_ids
            else {}
        )
        comments.setdefault(None)

        ids = self._tree.keys()
        children_tuples = cache.mget([self._cache_key(id) for id in ids]) if ids else []
        for idx, parent_id in enumerate(ids):
            # fill in missing children
            if children_tuples[idx] is None:
                children = (
                    Comment.where("parent_id", parent_id)
                    .where("link_id", self._link_id)
                    .get()
                )
                tuples = [[x.id, confidence(x.ups, x.downs)] for x in children]
                children_tuples[idx] = sorted(tuples, key=lambda x: x[1:], reverse=True)
                cache.set(self._cache_key(parent_id), children_tuples[idx])

        builder = dict(zip(ids, children_tuples))

        # subtree builder
        def build_subtree(parent):
            return [
                comments[parent],
                [build_subtree(children_id) for children_id, _ in builder[parent]]
                if parent in builder
                else [],
            ]

        return build_subtree(None)
Example #15
0
    def get_by_feed_id(cls, feed_id: int, sort: str) -> ["Link"]:
        """
        Get links by feed id and sort
        :param feed_id:
        :param sort:
        :return:
        """
        cache_key = "fs:{}.{}".format(feed_id, sort)

        r = cache.get(cache_key)
        if r is not None:
            return r

        q = Link.where("feed_id", feed_id).order_by_raw(sorts[sort])

        # cache needs array of objects, not a orator collection
        res = [f for f in q.limit(1000).get()]
        # TODO this is stupid, cache only ids?
        cache.set(cache_key, res)
        return res
Example #16
0
File: ban.py Project: matoous/newz
 def write_to_cache(self):
     """
     Write self to cache
     """
     cache.set(self.id, "y")
Example #17
0
File: feed.py Project: matoous/newz
 def rules(self, value):
     rules = markdown(value, safe_mode="escape")
     cache.set(self.rules_cache_key, rules)
     self.set_raw_attribute("rules", value)
Example #18
0
File: feed.py Project: matoous/newz
 def rules_html(self):
     rules = cache.get(self.rules_cache_key)
     if rules is None:
         rules = markdown(self.rules) if self.rules else ""
         cache.set(self.rules_cache_key, rules)
     return rules
Example #19
0
 def _save(self):
     """
     Save data to cache
     """
     assert self._fetched
     cache.set(self._cache_key, self._data)
Example #20
0
 def create(self):
     cache.set(self._cache_key, {})