Esempio n. 1
0
    def post(self):

        if not self.check_logged_in(self.min_perms):
            self.do_flickr_auth()
            return

        if not self.validate_crumb(self.user, 'optout',
                                   self.request.get('crumb')):
            self.assign('error', 'bad_crumb')
            self.display('deny.html')
            return

        if Membership.has_user_opted_out(self.user.nsid):
            self.assign('done', 1)
            self.display('deny.html')
            return

        if not self.request.get('confirm'):
            self.assign('error', 'no_confirm')
            self.display('deny.html')
            return

        Membership.opt_out(self.user.nsid)

        Suggestion.reject_all_pending_suggestions_for_owner(self.user.nsid)

        self.assign('done', 1)
        self.display('deny.html')
Esempio n. 2
0
  def post (self) :
    
    if not self.check_logged_in(self.min_perms) :
      self.do_flickr_auth()
      return

    if not self.validate_crumb(self.user, 'optout', self.request.get('crumb')) :
      self.assign('error', 'bad_crumb');
      self.display('deny.html')
      return

    if Membership.has_user_opted_out(self.user.nsid) :
      self.assign('done', 1)
      self.display('deny.html')
      return
    
    if not self.request.get('confirm') :
      self.assign('error', 'no_confirm')
      self.display('deny.html')
      return

    Membership.opt_out(self.user.nsid)
    
    Suggestion.reject_all_pending_suggestions_for_owner(self.user.nsid)
    
    self.assign('done', 1)
    self.display('deny.html')
Esempio n. 3
0
    def get(self, page=None):

        if not page:
            page = 1

        page = int(page)
        per_page = 10

        offset = (page - 1) * per_page

        res = dbFlickrUser.all().order("-created")
        count = res.count()

        users = res.fetch(per_page, offset)

        perms = dict([(v, k) for (k, v) in self.perms_map.iteritems()])

        for u in users:
            u.settings = Settings.get_settings_for_user(u.nsid)
            u.opted_out = Membership.has_user_opted_out(u.nsid)

            u.created_ymd = u.created.date
            u.perms_str = perms[u.perms]

            u.count_suggested_for = Suggestion.count_suggestions_for_user(
                u.nsid)

            u.count_suggested_by = Suggestion.count_suggestions_by_user(u.nsid)
            u.count_suggested_by_approved = Suggestion.count_suggestions_by_user(
                u.nsid, 2)
            u.count_suggested_by_rejected = Suggestion.count_suggestions_by_user(
                u.nsid, 3)

        pages = math.ceil(float(count) / float(per_page))

        if pages > page:
            self.assign("next", page + 1)

        if page > 1:
            self.assign("prev", page - 1)

        self.assign("count", count)
        self.assign("pages", pages)
        self.assign("page", page)
        self.assign("per_page", per_page)
        self.assign("offset", offset)

        self.assign("users", users)
        self.display("admin_users.html")
        return
Esempio n. 4
0
    def get(self):

        if not self.check_logged_in(self.min_perms):
            self.do_flickr_auth(self.min_perms)
            return

        approved = Suggestion.approved_suggestions_for_user(self.user.nsid)

        # please to put me in a pagination function...

        limit = 20
        offset = 0

        page = self.request.get('page')

        if page:
            offset = (page - 1) * limit

        #

        self.assign('count_approved', approved.count())
        self.assign('approved', approved.fetch(limit, offset))

        self.display('approved.html')
        return
Esempio n. 5
0
  def get (self) :
    
    if not self.check_logged_in(self.min_perms) :
      self.do_flickr_auth(self.min_perms)
      return

    approved = Suggestion.approved_suggestions_for_user(self.user.nsid)

    # please to put me in a pagination function...
    
    limit = 20
    offset = 0

    page = self.request.get('page')

    if page :
      offset = (page - 1) * limit

    #

    self.assign('count_approved', approved.count())
    self.assign('approved', approved.fetch(limit, offset))
    
    self.display('approved.html')
    return
Esempio n. 6
0
    def get (self, page=None) :

        if not page :
            page = 1

        page = int(page)
        per_page = 10

        offset = (page - 1) * per_page
        
        res = dbFlickrUser.all().order("-created")
        count = res.count()
        
        users = res.fetch(per_page, offset)

        perms = dict([(v, k) for (k, v) in self.perms_map.iteritems()])
        
        for u in users :
            u.settings = Settings.get_settings_for_user(u.nsid)
            u.opted_out = Membership.has_user_opted_out(u.nsid)

            u.created_ymd = u.created.date
            u.perms_str = perms[ u.perms ]
            
            u.count_suggested_for = Suggestion.count_suggestions_for_user(u.nsid)
            
            u.count_suggested_by = Suggestion.count_suggestions_by_user(u.nsid)
            u.count_suggested_by_approved = Suggestion.count_suggestions_by_user(u.nsid, 2)
            u.count_suggested_by_rejected = Suggestion.count_suggestions_by_user(u.nsid, 3)            
            
        pages = math.ceil(float(count) / float(per_page))
        
        if pages > page :
            self.assign("next", page + 1)

        if page > 1 : 
            self.assign("prev", page - 1)
        
        self.assign("count", count)
        self.assign("pages", pages)        
        self.assign("page", page)
        self.assign("per_page", per_page)
        self.assign("offset", offset)
        
        self.assign("users", users)
        self.display("admin_users.html")
        return
Esempio n. 7
0
    def run(self):
        required = ('crumb', 'suggestion_id')

        if not self.ensure_args(required):
            return

        if not self.ensure_crumb('method=reject'):
            return

        suggestion_id = self.request.get('suggestion_id')
        suggestion = self.fetch_pending_suggestion(suggestion_id)

        if not suggestion:
            return

        Suggestion.reject_suggestion(suggestion)
        return self.api_ok()
Esempio n. 8
0
    def run (self) :
        required = ('crumb', 'suggestion_id')

        if not self.ensure_args(required) :
            return 

        if not self.ensure_crumb('method=reject') :
            return

        suggestion_id = self.request.get('suggestion_id')
        suggestion = self.fetch_pending_suggestion(suggestion_id)
        
        if not suggestion:
            return 

        Suggestion.reject_suggestion(suggestion)
        return self.api_ok()
Esempio n. 9
0
  def get (self):

    if self.check_logged_in(self.min_perms) :
      pending = Suggestion.pending_suggestions_for_user(self.user.nsid)
      self.assign('pending_suggestions', pending.count())      
      self.assign('has_opted_out', Membership.has_user_opted_out(self.user.nsid))

    self.display('main.html')
Esempio n. 10
0
    def run (self) :

        required = ('crumb', 'user_id')

        if not self.ensure_args(required) :
            return 

        if not self.ensure_crumb('method=block') :
            return

        blocked_nsid = self.request.get('user_id')
        blocker_nsid = self.user.nsid
        
        # This will probably change
        
        Blocked.block_user(blocked_nsid, blocker_nsid)

        Suggestion.reject_all_pending_suggestions_for_owner(blocker_nsid, blocked_nsid)
        
        self.api_ok()
        return
Esempio n. 11
0
    def get(self, filter=None):

        if not self.check_logged_in(self.min_perms):
            self.do_flickr_auth(self.min_perms)
            return

        #

        photo_id = None
        page = None

        if filter:

            if filter.startswith("page"):
                page = filter.replace("page", "")
            else:
                photo_id = filter

        #

        default = self.default_geoperms()
        self.assign("geo_perms", default)

        #

        pending = Suggestion.pending_suggestions_for_user(
            self.user.nsid, photo_id)

        # please to put me in a pagination function...

        limit = 20
        offset = 0

        page = self.request.get('page')

        if page:
            offset = (page - 1) * limit

        #

        self.assign('count_pending', pending.count())
        self.assign('pending', pending.fetch(limit, offset))

        approve_crumb = self.generate_crumb(self.user, 'method=approve')
        reject_crumb = self.generate_crumb(self.user, 'method=reject')
        block_crumb = self.generate_crumb(self.user, 'method=block')

        self.assign('approve_crumb', approve_crumb)
        self.assign('reject_crumb', reject_crumb)
        self.assign('block_crumb', block_crumb)

        self.display('review.html')
        return
Esempio n. 12
0
  def get (self, filter=None) :
        
    if not self.check_logged_in(self.min_perms) :
      self.do_flickr_auth(self.min_perms)
      return

    #
    
    photo_id = None
    page = None

    if filter :

      if filter.startswith("page") :
        page = filter.replace("page", "")
      else :
        photo_id = filter

    #

    default = self.default_geoperms()
    self.assign("geo_perms", default)

    #
    
    pending = Suggestion.pending_suggestions_for_user(self.user.nsid, photo_id)

    # please to put me in a pagination function...
    
    limit = 20
    offset = 0

    page = self.request.get('page')

    if page :
      offset = (page - 1) * limit

    #

    self.assign('count_pending', pending.count())
    self.assign('pending', pending.fetch(limit, offset))

    approve_crumb = self.generate_crumb(self.user, 'method=approve')
    reject_crumb = self.generate_crumb(self.user, 'method=reject')
    block_crumb = self.generate_crumb(self.user, 'method=block')

    self.assign('approve_crumb', approve_crumb)
    self.assign('reject_crumb', reject_crumb)
    self.assign('block_crumb', block_crumb)
    
    self.display('review.html')
    return
Esempio n. 13
0
    def run(self):

        required = ('crumb', 'user_id')

        if not self.ensure_args(required):
            return

        if not self.ensure_crumb('method=block'):
            return

        blocked_nsid = self.request.get('user_id')
        blocker_nsid = self.user.nsid

        # This will probably change

        Blocked.block_user(blocked_nsid, blocker_nsid)

        Suggestion.reject_all_pending_suggestions_for_owner(
            blocker_nsid, blocked_nsid)

        self.api_ok()
        return
Esempio n. 14
0
  def fetch_pending_suggestion (self, suggestion_id) :

    suggestion = Suggestion.fetch_pending_suggestion(suggestion_id)
    
    if not suggestion :
      self.api_error(5, 'Not a valid suggestion ID')
      return False

    if suggestion.owner_nsid != self.user.nsid :
      self.api_error(6, 'Not a valid suggestion')
      return False

    if suggestion.status != 1 :
      self.api_error(7, 'Suggestion has already been ...')
      return False

    return suggestion
Esempio n. 15
0
    def fetch_pending_suggestion(self, suggestion_id):

        suggestion = Suggestion.fetch_pending_suggestion(suggestion_id)

        if not suggestion:
            self.api_error(5, 'Not a valid suggestion ID')
            return False

        if suggestion.owner_nsid != self.user.nsid:
            self.api_error(6, 'Not a valid suggestion')
            return False

        if suggestion.status != 1:
            self.api_error(7, 'Suggestion has already been ...')
            return False

        return suggestion
Esempio n. 16
0
    def run (self) :

        required = ('crumb', 'photo_id', 'owner_id', 'latitude', 'longitude')

        if not self.ensure_args(required) :
            return

        #
        # Context
        #

        geo_context = self.request.get('geo_context')

        if geo_context :

            geo_context = int(geo_context)

            if not geo_context in (0, 1, 2) :
                self.api_error(3, 'Not a valid geo context')
                return
        else :

            geo_context = 0

        #
        #
        #

        if not self.ensure_crumb('method=suggest') :
            return

        owner_nsid = self.request.get('owner_id')
        photo_id = long(self.request.get('photo_id'))

        #
        # Blocked?
        #

        if Blocked.is_user_blocked(self.user.nsid, owner_nsid) :
            self.api_error(3, 'You do not have permission to suggest a location for this photo.')
            return

        #
        # Opted out
        #

        if Membership.has_user_opted_out(owner_nsid) :
            self.api_error(4, 'You do not have permission to suggest a location for this photo.')
            return

        #
        # Already suggested?
        # This query will probably need to be less blunt
        #

        if Suggestion.has_pending_suggestions(photo_id, self.user.nsid) :
            self.api_error(999, 'Already suggested')
            return

        lat = float(self.request.get('latitude'))
        lon = float(self.request.get('longitude'))
        acc = int(self.request.get('accuracy'))
        woeid = self.request.get('woeid')

        if woeid != '' :
            woeid = int(woeid)

        #
        # grab the photo
        #

        method = 'flickr.photos.getInfo'

        args = {
            'photo_id' : photo_id,
        }

        rsp = self.proxy_api_call(method, args)

        #
        # Recordify!
        #

        owner_nsid = self.request.get('owner_id')

        args = {
            'photo_id' : photo_id,
            'owner_id' : owner_nsid,
            'latitude' : lat,
            'longitude' : lon,
            'accuracy' : acc,
            'woeid' : woeid,
            'suggestor_id' : self.user.nsid,
            'suggestor_name' : self.user.username,
            'context' : geo_context,
        }

        s = Suggestion.create(args)

        if not s :

            msg = "failed to add suggestion for %s" % str(args)
            self.log(msg, 'warning')

            self.api_error(2, 'There was a problem recording your suggestion.')
            return

        #
        # Notifications?
        #

        review_link = "%s/review/%s" % (self.request.host_url, photo_id)

        settings = Settings.get_settings_for_user(owner_nsid)

        if settings and settings.email_notifications :

            to_addr = settings.email_address
            subject = 'You have a new suggestion for one of your photos!'
            body = """Greetings from the Suggestify project!

Flickr user %s has suggested a location for your photo "%s".

To approve or reject this suggestion, follow the link below:

%s

(If you're tired of getting these email messages you can always disable email
notifications by going to: %s/settings/notifications)

Cheers,
            """ % (self.user.username, rsp['photo']['title']['_content'], review_link, self.request.host_url)

            Email.send(to=to_addr, subject=subject, body=body)

        #
        # Post comment to the photo on Flickr?
        #

        send_comment = False

        if config.config['notifications_flickr_comments'] and settings.comment_notifications :
            send_comment = True

        if self.user.perms != 2:
            send_comment = False
            self.log('not setting a comment; insufficient perms', 'info')

        if send_comment:

            # Do not display the lat,lon in the commment since they
            # are public for anyone to see. Only display WOE ID and name,
            # if we can find them.

            is_at = ""

            if woeid :

                method = 'flickr.places.getInfo'
                args = {'woe_id' : woeid}

                rsp = self.proxy_api_call(method, args)

                if rsp and rsp['stat'] == 'ok' and rsp.has_key('place') :
                    # note the trailing space at the end

                    is_at = """I think it was taken somewhere around: <a href="http://www.flickr.com/places/%s">%s</a>. """ % (woeid, rsp['place']['name'])

            # build the comment

            comment = """I've suggested a location for this photo over at the <a href="http://suggestify.appspot.com">Suggestify</a> project.

%sYou can see the exact location and approve or reject this suggestion by following this link:

<a href="%s">%s</a>

If you do approve the suggestion then your photo will be automagically geotagged!

(You can also <a href="http://suggestify.appspot.com/settings">configure Suggestify</a> to stop these notifications from being added to your photos or to prevent any of your photos from being "suggestified" at all in the future.)
""" % (is_at, review_link, review_link)

            # post the comment

            method = 'flickr.photos.comments.addComment'

            args = {
                'photo_id' : photo_id,
                'comment_text' : comment,
                'auth_token' : self.user.token,
                }

            rsp = self.api_call(method, args)

            # what is the right way to notify the user that
            # suggestion was recorded by the comment was not?

            if rsp and rsp['stat'] == 'ok':
                comment_id = rsp['comment']['id']
                s.comment_id = comment_id
                s.put()

            else :
                msg = 'Failed to post review comment: '

                if rsp :
                    msg += rsp['message']

                self.log(msg, 'warning')

        #
        # OKAY!
        #

        self.api_ok()
        return
Esempio n. 17
0
    def run (self) :

        required = ('crumb', 'suggestion_id', 'geo_perms', 'geo_context')
        
        if not self.ensure_args(required) :
            return 

        if not self.ensure_crumb('method=approve') :
            return

        suggestion_id = self.request.get('suggestion_id')
        suggestion = self.fetch_pending_suggestion(suggestion_id)
        
        if not suggestion:
            return 

        # Here's a potential problem: In order to do this properly
        # we may need to call the Flickr API (6) times and we're
        # doing all of them synchronously there's always the risk
        # that one of them will time out. Some possibilities include
        # doing the machinetag and comment stuff as queued tasks but
        # that probably puts too many eggs in the app engine basket.
        
        # Required:
        # flickr.photos.getInfo
        # flickr.photos.geo.setLocation

        # Possible:
        # flickr.photos.geo.setPerms        
        # flickr.photos.addTags
        # flickr.photos.comments.addComment
        
        #
        # Check to see if the photo has already been geotagged
        #
        
        args = {
            'photo_id' : suggestion.photo_id,
            'auth_token' : self.user.token,
            'check_response' : 1,
            }

        rsp = self.api_call('flickr.photos.getInfo', args)
        
        if not rsp :
            self.api_error(8, 'Unable to retrieve photo information from Flickr')
            return

        if rsp['photo'].has_key('location') :
            Suggestion.reject_all_pending_suggestions_for_photo(suggestion.photo_id)
        
            self.api_error(9, 'Photo has already been geotagged')
            return

        #
        # Also, this is all cloned in Robots/Suggestibot <-- it should probably
        # go in a "library" but the whole thing gets wrapped up in boring
        # object/globals/self nonsense and the fact that there aren't any
        # in Suggestion.py
        #
        
        #
        # Okay! Geotag the f*****g photo!!!
        #

        accuracy = suggestion.accuracy

        if accuracy > 16 :
            accuracy = 16
            
        args = {'photo_id' : suggestion.photo_id,
                'lat' : suggestion.latitude,
                'lon' : suggestion.longitude,
                'accuracy' : accuracy,
                'auth_token' : self.user.token,
                }

        geo_context = self.request.get('geo_context')
        
        if geo_context and int(geo_context) != 0 :
            args['context'] = geo_context
            
        rsp = self.api_call('flickr.photos.geo.setLocation', args)

        if not rsp :
            self.api_error(10, 'Failed to set location: Flickr API call failed')
            
        if rsp['stat'] != 'ok' :
            self.api_error(10, 'Failed to set location: %s (%s)' % (rsp['message'], rsp['code']))
            return

        #
        # Geo perms (it would be better if you could assign perms in setLocation...)
        #

        geoperms = int(self.request.get('geo_perms'))
        default = self.default_geoperms()

        if geoperms != default :

            method = 'flickr.photos.geo.setPerms'

            args = {
                'photo_id' : suggestion.photo_id,
                'auth_token' : self.user.token,
                'is_public' : 0,
                'is_contact' : 0,
                'is_family' : 0,
                'is_friend' : 0
            }
            
            if geoperms == 1 :
                args['is_public'] = 1
            elif geoperms == 2 :
                args['is_contact'] = 1
            elif geoperms == 3 :
                args['is_friend'] = 1
                args['is_family'] = 1
            elif geoperms == 4 :
                args['is_friend'] = 1                                
            elif geoperms == 5 :
                args['is_family'] = 1                
            else :
                pass

            rsp = self.api_call('flickr.photos.geo.setPerms', args)
    
            if rsp['stat'] != 'ok' :
                msg = 'Failed to set location: %s (%s)' % (rsp['message'], rsp['code'])
                self.log(msg, 'warning')
                pass

        #
        # geo:suggestedby= machine tag and comment-y reward
        # comment but only if the geo perms are public
        #

        if geoperms == 1 and suggestion.suggestor_nsid != self.user.nsid :

            suggested_by = suggestion.suggestor_nsid
            suggestor = User.get_user_by_nsid(suggestion.suggestor_nsid)
                    
            if suggestor and suggestor.path_alias :
                suggested_by = suggestor.path_alias

            tags = "geo:suggestedby=%s" % suggested_by
        
            machinetags_args = {
                'photo_id' : suggestion.photo_id,
                'tags' : tags,
                'auth_token' : self.user.token,
                'check_response' : 1,
                }

            rsp = self.api_call('flickr.photos.addTags', machinetags_args)

            # sudo make me a preference

            # TO DO: this should not be called "rewards" but it's early
            # and I haven't had much coffee....
            
            if self.user.nsid in config.rewards :

                suggested_date = suggestion.created.strftime("%B %d, %Y")
                suggestor_name = suggestor.username
                suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.nsid

                if suggestor.path_alias != '' :
                    suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.path_alias
                    
                # Note: don't lookup/display the place name for the WOE ID
                # until it's possible to do corrections on approval.

                nearby_url = "http://www.flickr.com/photos/%s/%s/nearby/?by=everyone&taken=recent&sort=distance&page=1&show=detail" % (self.user.nsid, suggestion.photo_id)
                
                comment = """On %s, <a href="%s">%s</a> suggested <a href="%s">where this photo was taken</a>, and they were right!
                """ % (suggested_date, suggestor_url, suggestor_name, nearby_url)

                method = 'flickr.photos.comments.addComment'
            
                comments_args = {
                    'photo_id' : suggestion.photo_id,
                    'comment_text' : comment,
                    'auth_token' : self.user.token,
                }
                
                rsp = self.api_call(method, comments_args)

                if not rsp :
                    logging.error("Failed to post approval comment")

                # TODO, MAYBE: delete initial suggestion comment here?
                
        #
        # Update (possibly do this before setting tags?)
        #
        
        Suggestion.approve_suggestion(suggestion)
        Suggestion.reject_all_pending_suggestions_for_photo(suggestion.photo_id)

        #
        # HAPPY
        #

        photo_owner = self.user.nsid

        if self.user.path_alias :
            photo_owner = self.user.path_alias
            
        photo_url = "http://www.flickr.com/photos/%s/%s" % (photo_owner, suggestion.photo_id)

        #
        
        out = {'photo_url' : photo_url}            
        return self.api_ok(out)
Esempio n. 18
0
    def post(self, uuid):

        is_api = True

        if not self.ensure_config(uuid):
            self.error('invalid_config', is_api)
            return

        if not self.check_logged_in(self.min_perms):
            self.do_flickr_auth(self.min_perms)
            return

        if not self.validate_crumb(self.user, 'method=approve',
                                   self.request.get('crumb')):
            self.error('invalid_perms', is_api)
            return False

        #
        # args/sig validation
        #

        req_args = ('photo_id', 'lat', 'lon', 'acc', 'context', '_s')
        sig_args = ['photo_id', 'lat', 'lon', 'acc', 'context', 'woeid']

        if not self.ensure_required_args(req_args):
            self.error('missing_args', is_api)
            return

        if not self.ensure_valid_args(req_args):
            self.error('invalid_args', is_api)
            return

        if not self.ensure_robot_sig(sig_args, self.request.get('_s')):
            self.error('invalid_sig')
            return

        args = {
            'photo_id': suggestion.photo_id,
            'auth_token': self.user.token,
            'check_response': 1,
        }

        rsp = self.api_call('flickr.photos.getInfo', args)

        if not rsp:
            self.error('invalid_photo')
            return

        if rsp['photo'].has_key('location'):
            Suggestion.reject_all_pending_suggestions_for_photo(
                suggestion.photo_id)
            self.error('already_geotagged')
            return

        mock = self.generate_mock_suggestion()

        if not mock:
            self.error('invalid suggestion')
            return

        suggestion = Suggestion.create(mock)

        #
        # this is all copy/pasted out of API/Approve <-- it should probably
        # go in a "library" but the whole thing gets wrapped up in boring
        # object/globals/self nonsense and the fact that there aren't any
        # in Suggestion.py
        #

        args = {
            'photo_id': suggestion.photo_id,
            'lat': suggestion.latitude,
            'lon': suggestion.longitude,
            'accuracy': suggestion.accuracy,
            'auth_token': self.user.token,
        }

        geo_context = self.request.get('geo_context')

        if geo_context and int(geo_context) != 0:
            args['context'] = geo_context

        rsp = self.api_call('flickr.photos.geo.setLocation', args)

        if not rsp:
            self.error('Failed to set location: Flickr API call failed',
                       is_api)
            return

        if rsp['stat'] != 'ok':
            self.error(
                'Failed to set location: %s (%s)' %
                (rsp['message'], rsp['code']), is_api)
            return

        geoperms = int(self.request.get('geo_perms'))
        default = self.default_geoperms()

        if geoperms != default:

            method = 'flickr.photos.geo.setPerms'

            args = {
                'photo_id': suggestion.photo_id,
                'auth_token': self.user.token,
                'is_public': 0,
                'is_contact': 0,
                'is_family': 0,
                'is_friend': 0
            }

            if geoperms == 1:
                args['is_public'] = 1
            elif geoperms == 2:
                args['is_contact'] = 1
            elif geoperms == 3:
                args['is_friend'] = 1
                args['is_family'] = 1
            elif geoperms == 4:
                args['is_friend'] = 1
            elif geoperms == 5:
                args['is_family'] = 1
            else:
                pass

            rsp = self.api_call('flickr.photos.geo.setPerms', args)

            if rsp['stat'] != 'ok':
                msg = 'Failed to set location: %s (%s)' % (rsp['message'],
                                                           rsp['code'])
                self.log(msg, 'warning')
                pass

        if geoperms == 1 and suggestion.suggestor_nsid != self.user.nsid:

            suggested_by = suggestion.suggestor_nsid

            suggestor = User.get_user_by_nsid(suggestion.suggestor_nsid)

            if suggestor and suggestor.path_alias:
                suggested_by = suggestor.path_alias

            tags = "geo:suggestedby=%s" % suggested_by

            args = {
                'photo_id': suggestion.photo_id,
                'tags': tags,
                'auth_token': self.user.token,
                'check_response': 1,
            }

            rsp = self.api_call('flickr.photos.addTags', args)

            # sudo make me a preference

            if self.user.nsid == 'brooklyn museum':

                suggested_date = suggestion.date_create
                suggestor_name = suggestor.username
                suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.nsid

                if suggestor.path_alias != '':
                    suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.path_alias

                # Note: don't lookup/display the place name for the WOE ID
                # until it's possible to do corrections on approval.

                comment = """On %s, <a href="%s">%s</a> suggested where this photo was taken, and they were right!
                """ % (suggested_date, suggestor_url, suggestor_name)

                method = 'flickr.photos.comments.addComment'

                comments_args = {
                    'photo_id': photo_id,
                    'comment_text': comment,
                    'auth_token': self.user.token,
                }

                rsp = self.api_call(method, args)

        #

        Suggestion.approve_suggestion(suggestion)
        Suggestion.reject_all_pending_suggestions_for_photo(
            suggestion.photo_id)

        #

        photo_owner = self.user.nsid

        if self.user.path_alias:
            photo_owner = self.user.path_alias

        photo_url = "http://www.flickr.com/photos/%s/%s" % (
            photo_owner, suggestion.photo_id)

        return self.ok({'photo_url': photo_url})
Esempio n. 19
0
    def run (self) :

        required = ('crumb', 'photo_id', 'owner_id', 'latitude', 'longitude')

        if not self.ensure_args(required) :
            return 

        #
        # Context
        #

        geo_context = self.request.get('geo_context')

        if geo_context :

            geo_context = int(geo_context)
            
            if not geo_context in (0, 1, 2) :
                self.api_error(3, 'Not a valid geo context')
                return
        else :

            geo_context = 0

        #
        #
        #
        
        if not self.ensure_crumb('method=suggest') :
            return

        owner_nsid = self.request.get('owner_id')
        photo_id = long(self.request.get('photo_id'))
        
        #
        # Blocked?
        #
    
        if Blocked.is_user_blocked(self.user.nsid, owner_nsid) :
            self.api_error(3, 'You do not have permission to suggest a location for this photo.')
            return

        #
        # Opted out
        #
        
        if Membership.has_user_opted_out(owner_nsid) :
            self.api_error(4, 'You do not have permission to suggest a location for this photo.')
            return
        
        #
        # Already suggested?
        # This query will probably need to be less blunt
        #

        if Suggestion.has_pending_suggestions(photo_id, self.user.nsid) :
            self.api_error(999, 'Already suggested')
            return

        lat = float(self.request.get('latitude'))
        lon = float(self.request.get('longitude'))
        acc = int(self.request.get('accuracy'))
        woeid = self.request.get('woeid')

        if woeid != '' :
            woeid = int(woeid)
            
        #
        # grab the photo
        #

        method = 'flickr.photos.getInfo'
        
        args = {
            'photo_id' : photo_id,
        }
        
        rsp = self.proxy_api_call(method, args)
        
        #
        # Recordify!
        #
        
        owner_nsid = self.request.get('owner_id')
        
        args = {
            'photo_id' : photo_id,
            'owner_id' : owner_nsid,
            'latitude' : lat,
            'longitude' : lon,
            'accuracy' : acc,
            'woeid' : woeid,
            'suggestor_id' : self.user.nsid,
            'suggestor_name' : self.user.username,
            'context' : geo_context,
        }

        s = Suggestion.create(args)
        
        if not s :

            msg = "failed to add suggestion for %s" % str(args)
            self.log(msg, 'warning')
            
            self.api_error(2, 'There was a problem recording your suggestion.')
            return

        #
        # Notifications?
        #

        review_link = "%s/review/%s" % (self.request.host_url, photo_id)
            
        settings = Settings.get_settings_for_user(owner_nsid)

        if settings and settings.email_notifications :
            
            to_addr = settings.email_address
            subject = 'You have a new suggestion for one of your photos!'
            body = """Greetings from the Suggestify project!

Flickr user %s has suggested a location for your photo "%s".

To approve or reject this suggestion, follow the link below:

%s

(If you're tired of getting these email messages you can always disable email
notifications by going to: %s/settings/notifications)

Cheers,
            """ % (self.user.username, rsp['photo']['title']['_content'], review_link, self.request.host_url)

            Email.send(to=to_addr, subject=subject, body=body)

        #
        # Post comment to the photo on Flickr?
        #

        if config.config['notifications_flickr_comments'] and settings.comment_notifications  :

            # Do not display the lat,lon in the commment since they
            # are public for anyone to see. Only display WOE ID and name,
            # if we can find them. 

            is_at = ""
            
            if woeid :

                method = 'flickr.places.getInfo'
                args = {'woe_id' : woeid}

                rsp = self.proxy_api_call(method, args)

                if rsp and rsp['stat'] == 'ok' and rsp.has_key('place') :
                    # note the trailing space at the end
                    
                    is_at = """I think it was taken somewhere around: <a href="http://www.flickr.com/places/%s">%s</a>. """ % (woeid, rsp['place']['name'])
                    
            # build the comment
            
            comment = """I've suggested a location for this photo over at the <a href="http://suggestify.appspot.com">Suggestify</a> project.

%sYou can see the exact location and approve or reject this suggestion by following this link:

<a href="%s">%s</a>

If you do approve the suggestion then your photo will be automagically geotagged!

(You can also <a href="http://suggestify.appspot.com/settings">configure Suggestify</a> to stop these notifications from being added to your photos or to prevent any of your photos from being "suggestified" at all in the future.)
""" % (is_at, review_link, review_link)

            # post the comment
            
            method = 'flickr.photos.comments.addComment'
            
            args = {
                'photo_id' : photo_id,
                'comment_text' : comment,
                'auth_token' : self.user.token,
                }

            rsp = self.api_call(method, args)

            # what is the right way to notify the user that
            # suggestion was recorded by the comment was not?
            
            if rsp and rsp['stat'] :
                comment_id = rsp['comment']['id']
                s.comment_id = comment_id
                s.put()
                
            else :
                msg = 'Failed to post review comment: '

                if rsp :
                    msg += rsp['message']
                    
                self.log(msg, 'warning')
                
        #
        # OKAY!
        #
        
        self.api_ok()
        return
Esempio n. 20
0
    def run(self):

        required = ('crumb', 'suggestion_id', 'geo_perms', 'geo_context')

        if not self.ensure_args(required):
            return

        if not self.ensure_crumb('method=approve'):
            return

        suggestion_id = self.request.get('suggestion_id')
        suggestion = self.fetch_pending_suggestion(suggestion_id)

        if not suggestion:
            return

        # Here's a potential problem: In order to do this properly
        # we may need to call the Flickr API (6) times and we're
        # doing all of them synchronously there's always the risk
        # that one of them will time out. Some possibilities include
        # doing the machinetag and comment stuff as queued tasks but
        # that probably puts too many eggs in the app engine basket.

        # Required:
        # flickr.photos.getInfo
        # flickr.photos.geo.setLocation

        # Possible:
        # flickr.photos.geo.setPerms
        # flickr.photos.addTags
        # flickr.photos.comments.addComment

        #
        # Check to see if the photo has already been geotagged
        #

        args = {
            'photo_id': suggestion.photo_id,
            'auth_token': self.user.token,
            'check_response': 1,
        }

        rsp = self.api_call('flickr.photos.getInfo', args)

        if not rsp:
            self.api_error(8,
                           'Unable to retrieve photo information from Flickr')
            return

        if rsp['photo'].has_key('location'):
            Suggestion.reject_all_pending_suggestions_for_photo(
                suggestion.photo_id)

            self.api_error(9, 'Photo has already been geotagged')
            return

        #
        # Also, this is all cloned in Robots/Suggestibot <-- it should probably
        # go in a "library" but the whole thing gets wrapped up in boring
        # object/globals/self nonsense and the fact that there aren't any
        # in Suggestion.py
        #

        #
        # Okay! Geotag the f*****g photo!!!
        #

        accuracy = suggestion.accuracy

        if accuracy > 16:
            accuracy = 16

        args = {
            'photo_id': suggestion.photo_id,
            'lat': suggestion.latitude,
            'lon': suggestion.longitude,
            'accuracy': accuracy,
            'auth_token': self.user.token,
        }

        geo_context = self.request.get('geo_context')

        if geo_context and int(geo_context) != 0:
            args['context'] = geo_context

        rsp = self.api_call('flickr.photos.geo.setLocation', args)

        if not rsp:
            self.api_error(10,
                           'Failed to set location: Flickr API call failed')

        if rsp['stat'] != 'ok':
            self.api_error(
                10, 'Failed to set location: %s (%s)' %
                (rsp['message'], rsp['code']))
            return

        #
        # Geo perms (it would be better if you could assign perms in setLocation...)
        #

        geoperms = int(self.request.get('geo_perms'))
        default = self.default_geoperms()

        if geoperms != default:

            method = 'flickr.photos.geo.setPerms'

            args = {
                'photo_id': suggestion.photo_id,
                'auth_token': self.user.token,
                'is_public': 0,
                'is_contact': 0,
                'is_family': 0,
                'is_friend': 0
            }

            if geoperms == 1:
                args['is_public'] = 1
            elif geoperms == 2:
                args['is_contact'] = 1
            elif geoperms == 3:
                args['is_friend'] = 1
                args['is_family'] = 1
            elif geoperms == 4:
                args['is_friend'] = 1
            elif geoperms == 5:
                args['is_family'] = 1
            else:
                pass

            rsp = self.api_call('flickr.photos.geo.setPerms', args)

            if rsp['stat'] != 'ok':
                msg = 'Failed to set location: %s (%s)' % (rsp['message'],
                                                           rsp['code'])
                self.log(msg, 'warning')
                pass

        #
        # geo:suggestedby= machine tag and comment-y reward
        # comment but only if the geo perms are public
        #

        if geoperms == 1 and suggestion.suggestor_nsid != self.user.nsid:

            suggested_by = suggestion.suggestor_nsid
            suggestor = User.get_user_by_nsid(suggestion.suggestor_nsid)

            if suggestor and suggestor.path_alias:
                suggested_by = suggestor.path_alias

            tags = "geo:suggestedby=%s" % suggested_by

            machinetags_args = {
                'photo_id': suggestion.photo_id,
                'tags': tags,
                'auth_token': self.user.token,
                'check_response': 1,
            }

            rsp = self.api_call('flickr.photos.addTags', machinetags_args)

            # sudo make me a preference

            # TO DO: this should not be called "rewards" but it's early
            # and I haven't had much coffee....

            if self.user.nsid in config.rewards:

                suggested_date = suggestion.created.strftime("%B %d, %Y")
                suggestor_name = suggestor.username
                suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.nsid

                if suggestor.path_alias != '':
                    suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.path_alias

                # Note: don't lookup/display the place name for the WOE ID
                # until it's possible to do corrections on approval.

                nearby_url = "http://www.flickr.com/photos/%s/%s/nearby/?by=everyone&taken=recent&sort=distance&page=1&show=detail" % (
                    self.user.nsid, suggestion.photo_id)

                comment = """On %s, <a href="%s">%s</a> suggested <a href="%s">where this photo was taken</a>, and they were right!
                """ % (suggested_date, suggestor_url, suggestor_name,
                       nearby_url)

                method = 'flickr.photos.comments.addComment'

                comments_args = {
                    'photo_id': suggestion.photo_id,
                    'comment_text': comment,
                    'auth_token': self.user.token,
                }

                rsp = self.api_call(method, comments_args)

                if not rsp:
                    logging.error("Failed to post approval comment")

                # TODO, MAYBE: delete initial suggestion comment here?

        #
        # Update (possibly do this before setting tags?)
        #

        Suggestion.approve_suggestion(suggestion)
        Suggestion.reject_all_pending_suggestions_for_photo(
            suggestion.photo_id)

        #
        # HAPPY
        #

        photo_owner = self.user.nsid

        if self.user.path_alias:
            photo_owner = self.user.path_alias

        photo_url = "http://www.flickr.com/photos/%s/%s" % (
            photo_owner, suggestion.photo_id)

        #

        out = {'photo_url': photo_url}
        return self.api_ok(out)
Esempio n. 21
0
    def post (self, uuid) :

        is_api = True

        if not self.ensure_config(uuid) :
            self.error('invalid_config', is_api)
            return
        
        if not self.check_logged_in(self.min_perms) :
            self.do_flickr_auth(self.min_perms)
            return

        if not self.validate_crumb(self.user, 'method=approve', self.request.get('crumb')) :
            self.error('invalid_perms', is_api)
            return False

        #
        # args/sig validation
        #

        req_args = ('photo_id', 'lat', 'lon', 'acc', 'context', '_s')
        sig_args = ['photo_id', 'lat', 'lon', 'acc', 'context', 'woeid']

        if not self.ensure_required_args(req_args) :
            self.error('missing_args', is_api)
            return

        if not self.ensure_valid_args(req_args) :
            self.error('invalid_args', is_api)
            return

        if not self.ensure_robot_sig(sig_args, self.request.get('_s')) :
            self.error('invalid_sig')
            return    

        args = {
            'photo_id' : suggestion.photo_id,
            'auth_token' : self.user.token,
            'check_response' : 1,
            }

        rsp = self.api_call('flickr.photos.getInfo', args)
        
        if not rsp :
            self.error('invalid_photo')
            return

        if rsp['photo'].has_key('location') :
            Suggestion.reject_all_pending_suggestions_for_photo(suggestion.photo_id)
            self.error('already_geotagged')
            return
        
        mock = self.generate_mock_suggestion()

        if not mock :
            self.error('invalid suggestion')
            return
        
        suggestion = Suggestion.create(mock)

        #
        # this is all copy/pasted out of API/Approve <-- it should probably
        # go in a "library" but the whole thing gets wrapped up in boring
        # object/globals/self nonsense and the fact that there aren't any
        # in Suggestion.py
        #
                    
        args = {'photo_id' : suggestion.photo_id,
                'lat' : suggestion.latitude,
                'lon' : suggestion.longitude,
                'accuracy' : suggestion.accuracy,
                'auth_token' : self.user.token,
                }

        geo_context = self.request.get('geo_context')
        
        if geo_context and int(geo_context) != 0 :
            args['context'] = geo_context
            
        rsp = self.api_call('flickr.photos.geo.setLocation', args)

        if not rsp :
            self.error('Failed to set location: Flickr API call failed', is_api)
            return
        
        if rsp['stat'] != 'ok' :
            self.error('Failed to set location: %s (%s)' % (rsp['message'], rsp['code']), is_api)
            return

        geoperms = int(self.request.get('geo_perms'))
        default = self.default_geoperms()

        if geoperms != default :

            method = 'flickr.photos.geo.setPerms'

            args = {
                'photo_id' : suggestion.photo_id,
                'auth_token' : self.user.token,
                'is_public' : 0,
                'is_contact' : 0,
                'is_family' : 0,
                'is_friend' : 0
            }
            
            if geoperms == 1 :
                args['is_public'] = 1
            elif geoperms == 2 :
                args['is_contact'] = 1
            elif geoperms == 3 :
                args['is_friend'] = 1
                args['is_family'] = 1
            elif geoperms == 4 :
                args['is_friend'] = 1                                
            elif geoperms == 5 :
                args['is_family'] = 1                
            else :
                pass

            rsp = self.api_call('flickr.photos.geo.setPerms', args)
    
            if rsp['stat'] != 'ok' :
                msg = 'Failed to set location: %s (%s)' % (rsp['message'], rsp['code'])
                self.log(msg, 'warning')
                pass
        
        if geoperms == 1 and suggestion.suggestor_nsid != self.user.nsid :

            suggested_by = suggestion.suggestor_nsid

            suggestor = User.get_user_by_nsid(suggestion.suggestor_nsid)
                    
            if suggestor and suggestor.path_alias :
                suggested_by = suggestor.path_alias
            
            tags = "geo:suggestedby=%s" % suggested_by
        
            args = {
                'photo_id' : suggestion.photo_id,
                'tags' : tags,
                'auth_token' : self.user.token,
                'check_response' : 1,
                }
        
            rsp = self.api_call('flickr.photos.addTags', args)

            # sudo make me a preference
            
            if self.user.nsid == 'brooklyn museum' :

                suggested_date = suggestion.date_create
                suggestor_name = suggestor.username
                suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.nsid

                if suggestor.path_alias != '' :
                    suggestor_url = 'http://www.flickr.com/photos/%s' % suggestor.path_alias
                    
                # Note: don't lookup/display the place name for the WOE ID
                # until it's possible to do corrections on approval.
                
                comment = """On %s, <a href="%s">%s</a> suggested where this photo was taken, and they were right!
                """ % (suggested_date, suggestor_url, suggestor_name)

                method = 'flickr.photos.comments.addComment'
            
                comments_args = {
                    'photo_id' : photo_id,
                    'comment_text' : comment,
                    'auth_token' : self.user.token,
                }
                
                rsp = self.api_call(method, args)

        #
        
        Suggestion.approve_suggestion(suggestion)
        Suggestion.reject_all_pending_suggestions_for_photo(suggestion.photo_id)
        
        #
        
        photo_owner = self.user.nsid

        if self.user.path_alias :
            photo_owner = self.user.path_alias
            
        photo_url = "http://www.flickr.com/photos/%s/%s" % (photo_owner, suggestion.photo_id)

        return self.ok({'photo_url' : photo_url})