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')
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')
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
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
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
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
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()
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()
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')
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
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
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
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
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
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
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
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)
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})
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
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)
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})