Example #1
0
    def anno_my_stuff(self, request):
        """
        Exposes an API endpoint to return all my anno list.
        """
        user = auth_user(self.request_state.headers)
        anno_list = Anno.query_anno_by_author(user)
        vote_list = Vote.query_vote_by_author(user)
        for vote in vote_list:
            anno = Anno.get_by_id(vote.anno_key.id())
            if anno is not None:
                anno_list.append(anno)
        flag_list = Flag.query_flag_by_author(user)
        for flag in flag_list:
            anno = Anno.get_by_id(flag.anno_key.id())
            if anno is not None:
                anno_list.append(anno)
        followup_list = FollowUp.query_followup_by_author(user)
        for followup in followup_list:
            anno = Anno.get_by_id(followup.anno_key.id())
            if anno is not None:
                anno_list.append(anno)
        anno_set = list(set(anno_list))

        anno_message_list = []
        for anno in anno_set:
            anno_message_list.append(anno.to_response_message())
        return AnnoListMessage(anno_list=anno_message_list)
Example #2
0
    def flag_delete(self, request):
        """
        Exposes an API endpoint to delete an existing flag.
        """
        user = auth_user(self.request_state.headers)
        anno = None
        if request.id is None and request.anno_id is None:
            raise endpoints.BadRequestException('id or anno_id field is required.')
        if request.id is not None:
            flag = Flag.get_by_id(request.id)
            if flag is None:
                raise endpoints.NotFoundException('No flag entity with the id "%s" exists.' % request.id)

            anno = flag.anno_key.get()
            flag.key.delete()
            anno.flag_count -= 1
            anno.put()
        elif request.anno_id is not None:
            anno = Anno.get_by_id(request.anno_id)
            for key in Flag.query(Flag.anno_key == anno.key, Flag.creator == user.key).iter(keys_only=True):
                key.delete()
                anno.flag_count -= 1
                anno.put()
        put_search_document(anno.generate_search_document(), SearchIndexName.ANNO)
        return message_types.VoidMessage()
Example #3
0
    def vote_insert(self, request):
        """
        Exposes an API endpoint to insert a vote for the current user.
        """
        user = auth_user(self.request_state.headers)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        vote = Vote()
        vote.anno_key = anno.key
        vote.creator = user.key
        if request.created is not None:
            vote.created = request.created
        vote.put()

        anno.vote_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'vote'
        anno.last_update_type = 'create'
        anno.put()

        # update user anno state
        UserAnnoState.insert(user=user, anno=anno, type=AnnoActionType.UPVOTED)

        # update vote in search document
        put_search_document(anno.generate_search_document(), SearchIndexName.ANNO)

        return vote.to_message()
Example #4
0
    def anno_get(self, request):
        """
        Exposes an API endpoint to get an anno detail by the specified id.
        """
        try:
            user = auth_user(self.request_state.headers)
        except Exception:
            user = None

        if request.id is None:
            raise endpoints.BadRequestException('id field is required.')

        anno = Anno.get_by_id(request.id)

        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        # set anno basic properties
        anno_resp_message = anno.to_response_message(user, list_message=False)

        # set anno association with followups
        followups = FollowUp.find_by_anno(anno)
        followup_messages = [ entity.to_message(team_key=request.team_key) for entity in followups ]
        anno_resp_message.followup_list = followup_messages

        # set anno association with votes/flags
        # if current user exists, then fetch vote/flag.
        if user is not None:
            anno_resp_message.is_my_vote = Vote.is_belongs_user(anno, user)
            anno_resp_message.is_my_flag = Flag.is_belongs_user(anno, user)

            # update last_read of UserAnnoState
            UserAnnoState.update_last_read(user=user, anno=anno)

        return anno_resp_message
Example #5
0
    def followup_insert(self, request):
        """
        Exposes and API endpoint to insert a follow up for the current user.
        """
        user = auth_user(self.request_state.headers)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        followup = FollowUp()
        followup.anno_key = anno.key
        followup.creator = user.key
        followup.comment = request.comment
        if request.created is not None:
            followup.created = request.created
        followup.put()

        anno.followup_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'follwup'
        anno.last_update_type = 'create'
        anno.put()
        # update search document
        put_search_document(anno.generate_search_document())
        return followup.to_message()
Example #6
0
    def anno_merge(self, request):
        """
        Exposes an API endpoint to merge(update only the specified properties) an anno.
        """
        user = auth_user(self.request_state.headers)

        if request.id is None:
            raise endpoints.BadRequestException('id field is required.')

        anno = Anno.get_by_id(request.id)

        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        anno.merge_from_message(request, user)
        # set last update time & activity
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'anno'
        anno.put()

        # update search document.
        put_search_document(anno.generate_search_document(), SearchIndexName.ANNO)

        # send notifications
        ActivityPushNotifications.send_push_notification(first_user=user, anno=anno, action_type=AnnoActionType.EDITED)

        # update last_read of UserAnnoState
        from model.userannostate import UserAnnoState
        UserAnnoState.update_last_read(user=user, anno=anno)

        return anno.to_response_message(user)
Example #7
0
    def flag_insert(self, request):
        """
        Exposes an API endpoint to insert a flag for the current user.
        """
        user = auth_user(self.request_state.headers)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.')

        flag = Flag()
        flag.anno_key = anno.key
        flag.creator = user.key
        if request.created is not None:
            flag.created = request.created
        flag.put()

        anno.flag_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'flag'
        anno.last_update_type = 'create'
        anno.put()

        # update user anno state
        UserAnnoState.insert(user=user, anno=anno, type=AnnoActionType.FLAGGED)

        # update flag in search document
        put_search_document(anno.generate_search_document(), SearchIndexName.ANNO)

        return flag.to_message()
Example #8
0
    def delete_by_anno(cls, anno_id=None, anno_key=None):
        if anno_key is None:
            anno = Anno.get_by_id(anno_id) if anno_id else None
            anno_key = anno.key if anno else None

        if anno_key:
            userannostates = cls.query(cls.anno == anno_key).fetch()
            userannostate_key_list = [ userannostate.key for userannostate in userannostates ]
            ndb.delete_multi(userannostate_key_list)
Example #9
0
    def delete_by_anno(cls, anno_id=None, anno_key=None):
        if anno_key is None:
            anno = Anno.get_by_id(anno_id) if anno_id else None
            anno_key = anno.key if anno else None

        if anno_key:
            followups = cls.query(cls.anno_key == anno_key).fetch()
            followup_key_list = [ followup.key for followup in followups ]
            ndb.delete_multi(followup_key_list)
Example #10
0
    def delete_by_anno(cls, anno_id=None, anno_key=None):
        if anno_key is None:
            anno = Anno.get_by_id(anno_id) if anno_id else None
            anno_key = anno.key if anno else None

        if anno_key:
            flags = cls.query(cls.anno_key == anno_key).fetch()
            flag_key_list = [ flag.key for flag in flags ]
            ndb.delete_multi(flag_key_list)
Example #11
0
    def delete_by_anno(cls, anno_id=None, anno_key=None):
        if anno_key is None:
            anno = Anno.get_by_id(anno_id) if anno_id else None
            anno_key = anno.key if anno else None

        if anno_key:
            votes = cls.query(cls.anno_key == anno_key).fetch()
            vote_key_list = [ vote.key for vote in votes ]
            ndb.delete_multi(vote_key_list)
Example #12
0
 def anno_get(self, request):
     """
     Exposes an API endpoint to get an anno detail by the specified id.
     """
     if request.id is None:
         raise endpoints.BadRequestException('id field is required.')
     anno = Anno.get_by_id(request.id)
     if anno is None:
         raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)
     return anno.to_response_message()
Example #13
0
    def update_notify(self, request):
        user = auth_user(self.request_state.headers)
        anno = Anno.get_by_id(request.anno_id)
        entity = UserAnnoState.get(user=user, anno=anno)

        if entity:
            entity.notify = request.notify
            entity.put()

        return message_types.VoidMessage()
Example #14
0
 def anno_delete(self, request):
     """
     Exposes an API endpoint to delete an existing anno.
     """
     if request.id is None:
         raise endpoints.BadRequestException('id field is required.')
     anno = Anno.get_by_id(request.id)
     if anno is None:
         raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)
     anno.key.delete()
     return message_types.VoidMessage()
Example #15
0
    def get(self):
        """
        handle request for screenshot.

        sample: https://usersource-anno.appspot.com/screenshot?anno_id=5644572721938432
        """
        anno_id = self.request.get('anno_id')
        if anno_id is None or anno_id == '':
            self.response.set_status(400)
            self.response.out.write(u'anno_id parameter is required.')
        else:
            # is this an if-modified request
            if_modified_since =  self.request.headers.get('If-Modified-Since')
            if_none_match =  self.request.headers.get('If-None-Match')

            # Reply with a 304
            # we could guess that if the Anno image was never modified
            # we do not even have to read the database and return a 304
            # if (if_modified_since is not None and if_modified_since == anno.created.isoformat()) or \
            #     (if_none_match is not None and if_none_match == anno.created.isoformat()):

            # We trust the request blindly to save to DB read time
            if if_modified_since or if_none_match:
                self.response.status = 304
                return

            anno = Anno.get_by_id(long(anno_id))
            if anno is None:
                self.response.set_status(400)
                self.response.out.write('No anno entity with the id "%s" exists.' % anno_id)
            elif anno.image is None:
                self.response.set_status(404)
                self.response.out.write("This anno doesn't contain screenshot")
            else:

                # Header identifier
                head = list(anno.image[:32])

                # Cache control and ETag support
                self.response.headers['Cache-Control'] = 'max-age=%d, public'%self.MAX_AGE
                self.response.headers['Last-Modified'] = anno.created.isoformat()
                self.response.headers['ETag'] = anno.created.isoformat()

                if self.HEADER_PNG == head[:len(self.HEADER_PNG)]:
                    # PNG Header
                    self.response.headers['Content-Type'] = 'image/png'
                elif self.HEADER_JPG == head[:len(self.HEADER_JPG)]:
                    # JPEG Header
                    self.response.headers['Content-Type'] = 'image/jpeg'
                else:
                    # Defaulting to BMP for now
                    self.response.headers['Content-Type'] = 'image/bmp'

                self.response.out.write(anno.image)
Example #16
0
    def list_users_by_anno(cls, anno_id=None, anno_key=None, projection=[]):
        if not anno_key:
            anno = Anno.get_by_id(anno_id)
            anno_key = anno.key if anno else None

        users = []
        if anno_key:
            query = cls.query().filter(ndb.AND(cls.anno == anno_key, cls.notify == True))
            users = query.fetch(projection=projection)

        return users
Example #17
0
    def anno_merge(self, request):
        """
        Exposes an API endpoint to merge(update only the specified properties) an anno.
        """
        if request.id is None:
            raise endpoints.BadRequestException('id field is required.')
        anno = Anno.get_by_id(request.id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        anno.merge_from_message(request)
        anno.put()
        return anno.to_response_message()
Example #18
0
    def anno_search(self, request):
        """
        Exposes and API endpoint to search anno list.
        """
        user = auth_user(self.request_state.headers)

        if request.order_type is None:
            raise endpoints.BadRequestException('order_type field is required.')
        if request.order_type != 'recent' and request.order_type != 'active' and request.order_type != 'popular':
            raise endpoints.BadRequestException(
                'Invalid order_type field value, valid values are "recent", "active" and "popular"')

        app_set = None
        logging.info("only_my_apps=%s" % request.only_my_apps)
        if request.only_my_apps:
            app_set = set()
            for anno in Anno.query_anno_by_author(user):
                app_set.add(anno.app_name)
            for vote in Vote.query_vote_by_author(user):
                anno = Anno.get_by_id(vote.anno_key.id())
                if anno is not None:
                    app_set.add(anno.app_name)
            for flag in Flag.query_flag_by_author(user):
                anno = Anno.get_by_id(flag.anno_key.id())
                if anno is not None:
                    app_set.add(anno.app_name)
            for followup in FollowUp.query_followup_by_author(user):
                anno = Anno.get_by_id(followup.anno_key.id())
                if anno is not None:
                    app_set.add(anno.app_name)

        if request.order_type == 'popular':
            return Anno.query_by_popular(request.limit, request.offset,
                                         request.search_string, request.app_name, app_set, user)
        elif request.order_type == 'active':
            return Anno.query_by_active(request.limit, request.offset, request.search_string, request.app_name, app_set, user)
        else:
            return Anno.query_by_recent(request.limit, request.offset, request.search_string, request.app_name, app_set, user)
Example #19
0
    def followup_insert(self, request):
        """
        Exposes and API endpoint to insert a follow up for the current user.
        """
        user = auth_user(self.request_state.headers)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        followup = FollowUp()
        followup.anno_key = anno.key
        followup.creator = user.key
        followup.comment = request.comment
        followup.tagged_users = request.tagged_users
        if request.created is not None:
            followup.created = request.created
        followup.put()

        anno.followup_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'follwup'
        anno.last_update_type = 'create'
        anno.put()

        # update user anno state
        UserAnnoState.insert(user=user, anno=anno, type=AnnoActionType.COMMENTED)

        for tagged_user_id in followup.tagged_users:
            tagged_user = User.get_by_id(int(tagged_user_id))
            if tagged_user:
                UserAnnoState.insert(user=tagged_user, anno=anno, type=AnnoActionType.TAGGEDUSER)

        # update search document
        put_search_document(anno.generate_search_document(), SearchIndexName.ANNO)
        put_search_document(followup.generate_search_document(), SearchIndexName.FOLLOWUP)

        # find all hashtags
        tags = extract_tags_from_text(followup.comment.lower())
        for tag, count in tags.iteritems():
            # Write the cumulative amount per tag
            Tag.add_tag_total(tag, total=count)

        # send notifications
        ActivityPushNotifications.send_push_notification(first_user=user, anno=anno, action_type=AnnoActionType.COMMENTED,
                                                         comment=request.comment)

        return followup.to_message(request.team_key)
Example #20
0
    def anno_merge(self, request):
        """
        Exposes an API endpoint to merge(update only the specified properties) an anno.
        """
        user = auth_user(self.request_state.headers)
        if request.id is None:
            raise endpoints.BadRequestException("id field is required.")
        anno = Anno.get_by_id(request.id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        anno.merge_from_message(request)
        # set last update time & activity
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = "anno"
        anno.put()
        return anno.to_response_message()
Example #21
0
 def get(self):
     """
     handle request for screenshot.
     """
     anno_id = self.request.get('anno_id')
     if anno_id is None or anno_id == '':
         self.response.set_status(400)
         self.response.out.write(u'anno_id parameter is required.')
     else:
         anno = Anno.get_by_id(long(anno_id))
         if anno is None:
             self.response.set_status(400)
             self.response.out.write('No anno entity with the id "%s" exists.' % anno_id)
         elif anno.image is None:
             self.response.set_status(404)
             self.response.out.write("This anno doesn't contain screenshot")
         else:
             self.response.out.write(anno.image)
Example #22
0
    def anno_delete(self, request):
        """
        Exposes an API endpoint to delete an existing anno.
        """
        user = auth_user(self.request_state.headers)

        if request.id is None:
            raise endpoints.BadRequestException('id field is required.')

        anno = Anno.get_by_id(request.id)

        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        # send notifications
        ActivityPushNotifications.send_push_notification(first_user=user, anno=anno, action_type=AnnoActionType.DELETED)

        Anno.delete(anno)
        return message_types.VoidMessage()
Example #23
0
    def get(self):
        """
        handle request for screenshot.

        sample: https://usersource-anno.appspot.com/screenshot?anno_id=5644572721938432
        """
        anno_id = self.request.get('anno_id')
        if anno_id is None or anno_id == '':
            self.response.set_status(400)
            self.response.out.write(u'anno_id parameter is required.')
        else:
            anno = Anno.get_by_id(long(anno_id))
            if anno is None:
                self.response.set_status(400)
                self.response.out.write('No anno entity with the id "%s" exists.' % anno_id)
            elif anno.image is None:
                self.response.set_status(404)
                self.response.out.write("This anno doesn't contain screenshot")
            else:
                self.response.headers['Content-Type'] = 'image/png'
                self.response.out.write(anno.image)
Example #24
0
 def vote_delete(self, request):
     """
     Exposes an API endpoint to delete an existing vote.
     """
     if request.id is None and request.anno_id is None:
         raise endpoints.BadRequestException('id or anno_id field is required.')
     if request.id is not None:
         vote = Vote.get_by_id(request.id)
         if vote is None:
             raise endpoints.NotFoundException('No vote entity with the id "%s" exists.' % request.id)
         anno = vote.anno_key.get()
         vote.key.delete()
         anno.vote_count -= 1
         anno.put()
     elif request.anno_id is not None:
         user = User.find_user_by_email(get_endpoints_current_user().email())
         anno = Anno.get_by_id(request.anno_id)
         for key in Vote.query(Vote.anno_key == anno.key, Vote.creator == user.key).iter(keys_only=True):
             key.delete()
             anno.vote_count -= 1
             anno.put()
     return message_types.VoidMessage()
Example #25
0
    def flag_insert(self, request):
        """
        Exposes an API endpoint to insert a flag for the current user.
        """
        user = handle_user(request.user_email)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.')

        flag = Flag()
        flag.anno_key = anno.key
        flag.creator = user.key
        if request.created is not None:
            flag.created = request.created
        flag.put()

        anno.flag_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'flag'
        anno.put()
        return flag.to_message()
Example #26
0
    def anno_teamnotes_insert(self, request):
        anno = Anno.get_by_id(request.id)
        user = auth_user(self.request_state.headers)

        if anno:
            anno.team_notes = request.team_notes
            UserAnnoState.tag_users(anno, anno.tagged_users, request.tagged_users)
            anno.tagged_users = request.tagged_users
            anno.put()

        mentions = []
        for tagged_user in request.tagged_users:
            user_info = User.get_by_id(int(tagged_user))
            is_auth_user = user_info.user_email == user.user_email
            mentions.append(AnnoMentionsResponseMessage(id=user_info.key.id(),
                                                        display_name=user_info.display_name,
                                                        user_email=user_info.user_email,
                                                        image_url=user_info.image_url,
                                                        is_auth_user=is_auth_user))

        return AnnoTeamNotesMetadataMessage(tags=parseTeamNotesForHashtags(request.team_notes),
                                            mentions=mentions)
Example #27
0
    def vote_insert(self, request):
        """
        Exposes an API endpoint to insert a vote for the current user.
        """
        user = handle_user(request.user_email)

        anno = Anno.get_by_id(request.anno_id)
        if anno is None:
            raise endpoints.NotFoundException('No anno entity with the id "%s" exists.' % request.id)

        vote = Vote()
        vote.anno_key = anno.key
        vote.creator = user.key
        if request.created is not None:
            vote.created = request.created
        vote.put()

        anno.vote_count += 1
        anno.last_update_time = datetime.datetime.now()
        anno.last_activity = 'vote'
        anno.put()
        return vote.to_message()