def post(self): if not self.check_logged_in(self.min_perms): self.do_flickr_auth(self.min_perms) return if not self.validate_crumb(self.user, 'optin', self.request.get('crumb')): self.assign('error', 'bad_crumb') self.display('deny.html') return if not Membership.has_user_opted_out(self.user.nsid): self.assign('done', 1) self.display('allow.html') return if not self.request.get('confirm'): self.assign('error', 'no_confirm') self.display('allow.html') return Membership.opt_in(self.user.nsid) self.assign('done', 1) self.display('allow.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 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(self.min_perms) return if not self.validate_crumb(self.user, 'optin', self.request.get('crumb')) : self.assign('error', 'bad_crumb'); self.display('deny.html') return if not Membership.has_user_opted_out(self.user.nsid) : self.assign('done', 1) self.display('allow.html') return if not self.request.get('confirm') : self.assign('error', 'no_confirm') self.display('allow.html') return Membership.opt_in(self.user.nsid) self.assign('done', 1) self.display('allow.html')
def check_logged_in (self, min_perms=None) : if not FlickrApp.check_logged_in(self, min_perms) : return False membership = Membership.retrieve(self.user.nsid) if not membership : membership = Membership.create(self.user.nsid) self.membership = membership self.has_opted_out = membership.opted_out return True
def check_logged_in(self, min_perms=None): if not FlickrApp.check_logged_in(self, min_perms): return False membership = Membership.retrieve(self.user.nsid) if not membership: membership = Membership.create(self.user.nsid) self.membership = membership self.has_opted_out = membership.opted_out return True
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 get (self) : if not self.check_logged_in(self.min_perms) : self.do_flickr_auth(self.min_perms) return crumb = self.generate_crumb(self.user, "optin") self.assign("optin_crumb", crumb) self.assign('has_opted_out', Membership.has_user_opted_out(self.user.nsid)) self.display("allow.html")
def get(self): if not self.check_logged_in(self.min_perms): self.do_flickr_auth(self.min_perms) return crumb = self.generate_crumb(self.user, "optin") self.assign("optin_crumb", crumb) self.assign('has_opted_out', Membership.has_user_opted_out(self.user.nsid)) self.display("allow.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, 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, context, filter) : min_perms = self.min_perms if self.request.get('perms') == 'write' : min_perms = 'write' if not self.check_logged_in(min_perms) : self.do_flickr_auth(min_perms) return # this is who I am ... if not context and self.request.get('user') : context = 'user' filter = self.request.get('user') self.assign('context', context) # Default, choose a user if not context : self.display('chooser.html') return # ok, what are we trying to do... other_user = None other_username = None if context == 'user' : other_username = filter elif context == 'photo' : # magic referer glue, mostly for the Brooklyn Museum headers = self.request.headers if headers.has_key('Referer') : u = urlparse.urlparse(headers['Referer']) m = re.match(r'(?:www\.)?flickr\.com', u[1]) if not m : self.error(404) return m = re.match(r'/photos/(?:[^/]+)/(\d+)', u[2]) if m : filter = m.groups()[0] else : self.error(404) return # end of magic glue method = 'flickr.photos.getInfo' args = { 'photo_id' : filter, 'auth_token' : self.user.token, } ttl = 60 * 60 rsp = self.proxy_api_call(method, args, ttl) if not rsp or not rsp.has_key('photo') : self.assign('error', 'no_photo') elif rsp['photo'].has_key('location') : self.assign('error', 'already_geotagged') else : # this is kind of dumb in the end... spr = { 'id': rsp['photo']['id'], 'owner' : rsp['photo']['owner']['nsid'], 'secret' : rsp['photo']['secret'], 'server' : rsp['photo']['server'], 'farm' : rsp['photo']['farm'], 'title' : rsp['photo']['title']['_content'], 'tags' : '', 'datetaken' : rsp['photo']['dates']['taken'], 'ownername' : rsp['photo']['owner']['username'], } if rsp['photo'].has_key('tags') : tags = map( lambda t: t['_content'], rsp['photo']['tags']['tag']) spr['tags'] = ' '.join(tags) json = simplejson.dumps({ 'photo' : [spr] }) self.assign("photo_json", json) other_username = rsp['photo']['owner']['username'] self.assign("usernsid", rsp['photo']['owner']['nsid']) elif context == 'random' : noidea_crumb = self.generate_crumb(self.user, 'method=noidea') self.assign('noidea_crumb', noidea_crumb); else : self.assign('error', 'unknown_context') # do some sanity checking on the user self.assign("username", other_username) if other_username : other_user = User.get_user_by_username(other_username) if other_user : if Blocked.is_user_blocked(self.user.nsid, other_user.nsid) : self.assign('blocked', 1) elif Membership.has_user_opted_out(other_user.nsid) : self.assign('optedout', 1) else : pass self.assign("other_user", other_user) # # crumbs crumb = self.generate_crumb(self.user, 'method=suggest') self.assign('suggest_crumb', crumb) # go! self.display('chooser.html') return
def run (self) : if self.request.get('page') != '' : page = self.request.get('page') page = 1 if self.request.get('page') : page = self.request.get('page') per_page = max(int(random.random() * 100), 25) sort = ['date-posted-asc', 'date-posted-desc', 'date-taken-asc', 'date-taken-desc', 'interestingness-desc', 'interestingness-asc', 'relevance'] random.shuffle(sort) random.shuffle(sort) contacts = ['ff', 'all'] random.shuffle(contacts) prop = random.random() format = "%Y-%m-%d" stime = time.mktime(time.strptime('1970-01-01', format)) etime = time.time() ptime = stime + prop * (etime - stime) date_taken = time.strftime(format, time.localtime(ptime)) method = 'flickr.photos.search' args = { 'auth_token' : self.user.token, 'user_id' : self.user.nsid, 'contacts' : contacts[0], 'has_geo' : 0, 'per_page' : per_page, 'page' : page, 'sort' : sort[0], 'max_taken_date' : "%s 00:00:00" % date_taken, 'extras' : 'owner_name,date_taken,tags' } ttl = 60 * 10 rsp = self.proxy_api_call(method, args, ttl) # wrong and dirty, please to fix self.format = 'json' if not rsp or rsp['stat'] != 'ok' : self.api_error(1, 'API call failed') return if rsp['photos']['total'] == 0 : self.api_error(2, 'Retry, no photos for query'); return # these always time out on localhost... if self.request.host.startswith("localhost") : self.api_ok({'photos' : rsp['photos']}) return skip_photos = [] unknown_photos = [] filtered = [] blocked_by = {} opted_out = {} # please to memcache all of this... gql = "SELECT * FROM dbSuggestion WHERE suggestor_nsid = :1" res = db.GqlQuery(gql, self.user.nsid) for ph in res.fetch(res.count()) : skip_photos.append(ph.photo_id) gql = "SELECT * FROM dbGamesRandom WHERE suggestor_nsid = :1" res = db.GqlQuery(gql, self.user.nsid) for ph in res.fetch(res.count()) : unknown_photos.append(ph.photo_id) for ph in rsp['photos']['photo'] : id = long(ph['id']) if id in skip_photos : continue if id in unknown_photos : continue # has the photo owner opted out photo_owner = ph['owner'] if not opted_out.has_key(photo_owner) : has_opted_out = Membership.has_user_opted_out(photo_owner) opted_out[photo_owner] = has_opted_out if opted_out[photo_owner] : continue # has the photo owner blocked this user if not blocked_by.has_key(photo_owner) : is_blocked = Blocked.is_user_blocked(self.user.nsid, photo_owner) blocked_by[photo_owner] = is_blocked if blocked_by[photo_owner] : continue filtered.append(ph) if len(filtered) == 0 : self.api_error(3, 'Retry, no photos post filter'); return rsp['photos']['photo'] = filtered self.api_ok({'photos' : rsp['photos']}) return
def get(self, context, filter): min_perms = self.min_perms if self.request.get('perms') == 'write': min_perms = 'write' if not self.check_logged_in(min_perms): self.do_flickr_auth(min_perms) return # this is who I am ... if not context and self.request.get('user'): context = 'user' filter = self.request.get('user') self.assign('context', context) # Default, choose a user if not context: self.display('chooser.html') return # ok, what are we trying to do... other_user = None other_username = None if context == 'user': other_username = filter elif context == 'photo': # magic referer glue, mostly for the Brooklyn Museum headers = self.request.headers if headers.has_key('Referer'): u = urlparse.urlparse(headers['Referer']) m = re.match(r'(?:www\.)?flickr\.com', u[1]) if not m: self.error(404) return m = re.match(r'/photos/(?:[^/]+)/(\d+)', u[2]) if m: filter = m.groups()[0] else: self.error(404) return # end of magic glue method = 'flickr.photos.getInfo' args = { 'photo_id': filter, 'auth_token': self.user.token, } ttl = 60 * 60 rsp = self.proxy_api_call(method, args, ttl) if not rsp or not rsp.has_key('photo'): self.assign('error', 'no_photo') elif rsp['photo'].has_key('location'): self.assign('error', 'already_geotagged') else: # this is kind of dumb in the end... spr = { 'id': rsp['photo']['id'], 'owner': rsp['photo']['owner']['nsid'], 'secret': rsp['photo']['secret'], 'server': rsp['photo']['server'], 'farm': rsp['photo']['farm'], 'title': rsp['photo']['title']['_content'], 'tags': '', 'datetaken': rsp['photo']['dates']['taken'], 'ownername': rsp['photo']['owner']['username'], } if rsp['photo'].has_key('tags'): tags = map(lambda t: t['_content'], rsp['photo']['tags']['tag']) spr['tags'] = ' '.join(tags) json = simplejson.dumps({'photo': [spr]}) self.assign("photo_json", json) other_username = rsp['photo']['owner']['username'] self.assign("usernsid", rsp['photo']['owner']['nsid']) elif context == 'random': noidea_crumb = self.generate_crumb(self.user, 'method=noidea') self.assign('noidea_crumb', noidea_crumb) else: self.assign('error', 'unknown_context') # do some sanity checking on the user self.assign("username", other_username) if other_username: other_user = User.get_user_by_username(other_username) if other_user: if Blocked.is_user_blocked(self.user.nsid, other_user.nsid): self.assign('blocked', 1) elif Membership.has_user_opted_out(other_user.nsid): self.assign('optedout', 1) else: pass self.assign("other_user", other_user) # # crumbs crumb = self.generate_crumb(self.user, 'method=suggest') self.assign('suggest_crumb', crumb) # go! self.display('chooser.html') return
def run(self): if self.request.get('page') != '': page = self.request.get('page') page = 1 if self.request.get('page'): page = self.request.get('page') per_page = max(int(random.random() * 100), 25) sort = [ 'date-posted-asc', 'date-posted-desc', 'date-taken-asc', 'date-taken-desc', 'interestingness-desc', 'interestingness-asc', 'relevance' ] random.shuffle(sort) random.shuffle(sort) contacts = ['ff', 'all'] random.shuffle(contacts) prop = random.random() format = "%Y-%m-%d" stime = time.mktime(time.strptime('1970-01-01', format)) etime = time.time() ptime = stime + prop * (etime - stime) date_taken = time.strftime(format, time.localtime(ptime)) method = 'flickr.photos.search' args = { 'auth_token': self.user.token, 'user_id': self.user.nsid, 'contacts': contacts[0], 'has_geo': 0, 'per_page': per_page, 'page': page, 'sort': sort[0], 'max_taken_date': "%s 00:00:00" % date_taken, 'extras': 'owner_name,date_taken,tags' } ttl = 60 * 10 rsp = self.proxy_api_call(method, args, ttl) # wrong and dirty, please to fix self.format = 'json' if not rsp or rsp['stat'] != 'ok': self.api_error(1, 'API call failed') return if rsp['photos']['total'] == 0: self.api_error(2, 'Retry, no photos for query') return # these always time out on localhost... if self.request.host.startswith("localhost"): self.api_ok({'photos': rsp['photos']}) return skip_photos = [] unknown_photos = [] filtered = [] blocked_by = {} opted_out = {} # please to memcache all of this... gql = "SELECT * FROM dbSuggestion WHERE suggestor_nsid = :1" res = db.GqlQuery(gql, self.user.nsid) for ph in res.fetch(res.count()): skip_photos.append(ph.photo_id) gql = "SELECT * FROM dbGamesRandom WHERE suggestor_nsid = :1" res = db.GqlQuery(gql, self.user.nsid) for ph in res.fetch(res.count()): unknown_photos.append(ph.photo_id) for ph in rsp['photos']['photo']: id = long(ph['id']) if id in skip_photos: continue if id in unknown_photos: continue # has the photo owner opted out photo_owner = ph['owner'] if not opted_out.has_key(photo_owner): has_opted_out = Membership.has_user_opted_out(photo_owner) opted_out[photo_owner] = has_opted_out if opted_out[photo_owner]: continue # has the photo owner blocked this user if not blocked_by.has_key(photo_owner): is_blocked = Blocked.is_user_blocked(self.user.nsid, photo_owner) blocked_by[photo_owner] = is_blocked if blocked_by[photo_owner]: continue filtered.append(ph) if len(filtered) == 0: self.api_error(3, 'Retry, no photos post filter') return rsp['photos']['photo'] = filtered self.api_ok({'photos': rsp['photos']}) return
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', '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