def photo(request, xid, template=None): # Ask this up front to get the user object outside of batches. authed = request.user.is_authenticated() lastface, elsewhere = None, None with typepad.client.batch_request(): photo = Asset.get_by_url_id(xid) favs = photo.favorites favfaces = dict() for face in Favoriteface.objects.all().filter(favorited=xid): favfaces[face.favoriter] = Asset.get_by_url_id(face.lastface) if authed: elsewhere = request.user.elsewhere_accounts try: lastface_mod = Lastface.objects.get(owner=request.user.xid) except Lastface.DoesNotExist: pass else: lastface = Asset.get_by_url_id(lastface_mod.face) userfav = None if authed: elsewhere = sharing_for_elsewhere(elsewhere) # Get the Favorite in a separate batch so we can handle if it fails. try: with typepad.client.batch_request(): userfav = Favorite.get_by_user_asset(request.user.xid, xid) except Favorite.NotFound: userfav = None # Annotate the favorites with the last faces, so we get them naturally in their loop. for fav in favs: try: fav.lastface = favfaces[fav.author.xid] except KeyError: pass if template is None: mobile_context = makeaface.context_processors.mobile(request) template = 'mobileface/photo.html' if mobile_context['mobile'] else 'makeaface/photo.html' return TemplateResponse(request, template, { 'photo': photo, 'favorites': favs, 'user_favorite': userfav, 'lastface': lastface, 'share': elsewhere, })
def favorite(request): if request.method != 'POST': return HttpResponse('POST required at this url', status=400, content_type='text/plain') if not request.user.is_authenticated(): return HttpResponse('silly rabbit, only signed-in folks can favorite', status=400, content_type='text/plain') action = request.POST.get('action', 'favorite') asset_id = request.POST.get('asset_id', '') try: (asset_id,) = re.findall('6a\w+', asset_id) except TypeError: raise Http404 if action != 'favorite': return HttpResponse('Unsupported action %r' % action, status=400, content_type='text/plain') with typepad.client.batch_request(): asset = Asset.get_by_url_id(asset_id) fav = Favorite() fav.in_reply_to = asset.asset_ref request.user.favorites.post(fav) typepadapp.signals.favorite_created.send(sender=fav, instance=fav, parent=asset, group=request.group) return HttpResponse('OK', content_type='text/plain')
def upload_photo(request): if request.method != 'POST': return HttpResponse('POST required at this url', status=400, content_type='text/plain') content_type = request.META['CONTENT_TYPE'] assert content_type.startswith('image/') bodyfile = StringIO(request.raw_post_data) target_url = request.group.photo_assets._location target_parts = urlparse(target_url) target_path = target_parts.path.replace('.json', '') log.debug('Using %r as target URL', target_path) asset = Asset() asset.title = "a face" resp, content = typepad.api.browser_upload.upload(asset, bodyfile, content_type=content_type, redirect_to='http://example.com/', target_url=target_path, post_type='photo') if resp.status != 302: log.debug('%d response from typepad: %s', resp.status, content) assert resp.status == 302 typepadapp.signals.asset_created.send(sender=asset, instance=asset, group=request.group, parent=request.group.photo_assets) if 'location' not in resp: log.debug('No Location in response, only %r', resp.keys()) loc = resp['location'] loc_parts = parse_qs(urlparse(loc).query) if 'asset_url' not in loc_parts: log.warning('New location was %r', loc) log.warning('Original response/content were %r, %r', resp, content) loc = loc_parts['asset_url'][0] log.debug('LOCATION IS A %s %r', type(loc).__name__, loc) with typepad.client.batch_request(): asset = Asset.get(loc) image_url = asset.image_link.square(150).url # Save the photo as a new last face for the poster. Lastface(owner=request.user.xid, face=asset.xid).save() # Flash doodad needs a 200, not a redirect. return HttpResponse(image_url, content_type='text/plain')
def oembed(request): # Ask this up front to get the user object outside of batches. authed = request.user.is_authenticated() url = request.GET['url'] urlparts = urlparse(url) view, args, kwargs = resolve(urlparts.path) if not getattr(view, 'is_photo_view', False): return HttpResponseNotFound('not a photo url', content_type='text/plain') if request.GET.get('format', 'json') != 'json': return HttpResponse('unsupported format :(', status=501, content_type='text/plain') xid = kwargs['xid'] maxwidth = request.GET.get('maxwidth') maxheight = request.GET.get('maxheight') if maxwidth and maxheight: size = maxwidth if maxwidth < maxheight else maxheight elif maxwidth: size = maxwidth elif maxheight: size = maxheight else: size = 500 typepad.client.batch_request() photo = Asset.get_by_url_id(xid) try: typepad.client.complete_batch() except Asset.NotFound: return HttpResponseNotFound('no such photo', content_type='text/plain') photo_url = photo.image_link.square(size).url data = { 'type': 'photo', 'version': '1.0', 'title': "%s's face" % photo.author.display_name, 'author_name': photo.author.display_name, 'provider_name': 'Make A Face', 'provider_url': 'http://make-a-face.org/', 'url': photo_url, 'width': size, 'height': size, } if size > 150: data.update({ 'thumbnail_url': photo.image_link.square(150).url, 'thumbnail_width': 150, 'thumbnail_height': 150, }) return HttpResponse(json.dumps(data), content_type='application/json+javascript')
def flag(request): if request.method != 'POST': return HttpResponse('POST required at this url', status=400, content_type='text/plain') action = request.POST.get('action', 'flag') asset_id = request.POST.get('asset_id', '') try: (asset_id,) = re.findall('6a\w+', asset_id) except TypeError: raise Http404 cache_key = 'flag:%s' % asset_id if action != 'flag': return HttpResponse('Only flag action is supported at this url', status=400, content_type='text/plain') # YAY UNATOMIC OPERATIONS flaggers = cache.get(cache_key) if not flaggers: log.debug('No flaggers for %r yet, making a new list', asset_id) flaggers = [] elif request.user.xid in flaggers: log.debug('%r re-flagged %r (ignored)', request.user.xid, asset_id) return HttpResponse('OK (though you already flagged it)', content_type='text/plain') flaggers.append(request.user.xid) if len(flaggers) >= 3: log.debug('%r was the last straw for %r! Deleting!', request.user.xid, asset_id) with typepad.client.batch_request(): # Re-authenticate the client with the superuser credentials that can delete that. typepad.client.clear_credentials() backend = urlparse(settings.BACKEND_URL) csr = OAuthConsumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET) token = OAuthToken(settings.OAUTH_SUPERUSER_KEY, settings.OAUTH_SUPERUSER_SECRET) typepad.client.add_credentials(csr, token, domain=backend[1]) asset = Asset.get_by_url_id(asset_id) asset.delete() typepadapp.signals.asset_deleted.send(sender=asset, instance=asset, group=request.group) del asset # lose our reference to it log.debug('BALEETED') cache.delete(cache_key) log.debug('Emptied flaggers for %r now that it is deleted', asset_id) return HttpResponse('BALEETED', content_type='text/plain') else: cache.set(cache_key, flaggers, ONE_DAY) log.debug('Flaggers for %r are now %r', asset_id, flaggers) return HttpResponse('OK', content_type='text/plain')
def favorite(request): if request.method != 'POST': return HttpResponse('POST required at this url', status=400, content_type='text/plain') action = request.POST.get('action', 'favorite') asset_id = request.POST.get('asset_id', '') try: (asset_id,) = re.findall('6a\w+', asset_id) except TypeError: raise Http404 if action == 'favorite': with typepad.client.batch_request(): asset = Asset.get_by_url_id(asset_id) fav = Favorite() fav.in_reply_to = asset.asset_ref request.user.favorites.post(fav) typepadapp.signals.favorite_created.send(sender=fav, instance=fav, parent=asset, group=request.group) # Save the user's last face when favorited. try: last = Lastface.objects.get(owner=request.user.xid) except Lastface.DoesNotExist: pass else: Favoriteface(favoriter=request.user.xid, favorited=asset_id, lastface=last.face).save() else: # Getting the xid will do a batch, so don't do it inside our other batch. xid = request.user.xid with typepad.client.batch_request(): asset = Asset.get_by_url_id(asset_id) fav = Favorite.get_by_user_asset(xid, asset_id) fav.delete() typepadapp.signals.favorite_deleted.send(sender=fav, instance=fav, parent=asset, group=request.group) return HttpResponse('OK', content_type='text/plain')
def entry(request, xid): with typepad.client.batch_request(): request.user = get_user(request) entry = Asset.get_by_url_id(xid) favs = entry.favorites audio = audio_from_asset(entry) add_tags_to_entries(((audio, entry),)) return TemplateResponse(request, 'sixaphone/entry.html', { 'entry': entry, 'audio': audio_from_asset(entry), 'favorites': favs, })
def delete(request): if request.method != 'POST': return HttpResponse('POST required at this url', status=400, content_type='text/plain') action = request.POST.get('action', 'delete') asset_id = request.POST.get('asset_id', '') try: (asset_id,) = re.findall('6a\w+', asset_id) except TypeError: raise Http404 if action == 'delete': # Getting the xid will do a batch, so don't do it inside our other batch. xid = request.user.xid with typepad.client.batch_request(): asset = Asset.get_by_url_id(asset_id) asset.delete() typepadapp.signals.asset_deleted.send(sender=asset, instance=asset, group=request.group) return HttpResponse('', status=204)
def tag(request, tag, page=1): page = int(page) first = (page - 1) * 10 last = first + 10 + 1 tags = Tag.objects.filter(tag=tag).order_by('-created')[first:last] has_next_page = True if len(tags) > 10 else False tags = tags[:10] with typepad.client.batch_request(): request.user = get_user(request) assets = [Asset.get_by_url_id(tagject.asset) for tagject in tags] audio_entries = list(audio_entries_from_entries(assets)) add_tags_to_entries(audio_entries) return TemplateResponse(request, 'sixaphone/tag.html', { 'audio_entries': audio_entries, 'tag': tag, 'page': page, 'prev_page': page - 1 if page > 1 else False, 'next_page': page + 1 if len(tags) > 10 else False, })
def facejson(request, page=None): resp = home(request, page, 'faces.json') events = resp.template_context['events'] events_data = list() for event in events: about_event = event.__dict__ obj = event.object if obj is None: continue author = obj.author author_data = { 'xid': author.xid, 'displayName': author.display_name, } event_data = { 'xid': obj.xid, 'url': obj.image_link.url, 'published': obj.published.replace(microsecond=0).isoformat(), 'author': author_data, } if obj.favorite_count > 0: xid = obj.xid with typepad.client.batch_request(): favs = Asset.get_by_url_id(xid).favorites favfaces = dict() for face in Favoriteface.objects.all().filter(favorited=xid): favfaces[face.favoriter] = Asset.get_by_url_id(face.lastface) favs_data = list() for fav in favs: author = fav.author fav_data = { 'xid': author.xid, 'displayName': author.display_name, 'favorited': fav.published.replace(microsecond=0).isoformat(), } if author.xid in favfaces: face = favfaces[author.xid] face_data = { 'xid': face.xid, 'url': face.image_link.url, 'published': face.published.replace(microsecond=0).isoformat(), } fav_data['face'] = face_data favs_data.append(fav_data) event_data['favorites'] = favs_data events_data.append(event_data) next_page = resp.template_context['next_page'] next_url = reverse('facejson', kwargs={'page': next_page}) next_url = request.build_absolute_uri(next_url) data = { 'events': events_data, 'next': next_url, } prev_page = resp.template_context['prev_page'] if prev_page > 0: prev_url = reverse('facejson', kwargs={'page': prev_page}) prev_url = request.build_absolute_uri(prev_url) data['prev'] = prev_url jsontext = json.dumps(data, sort_keys=True, indent=4) return HttpResponse(jsontext, content_type='application/json')