def room(request, nickname): '''Render a room feed. Authentication is not required but is used if set. nickname is the room's nickname. ''' if request.session.get('nickname', None): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) else: f = friendfeed.FriendFeed() start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) data = f.fetch_room_feed(nickname, **request_to_feed_args_dict(request)) if 'errorCode' in data: return error(request, data) profile = f.fetch_room_profile(nickname) entries = [entry for entry in data['entries'] if not entry['hidden']] hidden = [entry for entry in data['entries'] if entry['hidden']] extra_context = { 'entries': entries, 'next': start + num, 'hidden': hidden, 'profile': profile, 'room': nickname, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('room.html', extra_context, context_instance=RequestContext(request))
def search(request): '''Render a search feed. Authentication is not required but is used if set. Search operates on a 'search' paramater in the GET dict that works the same way the FriendFeed search works (who:everyone would search the public feed). ''' if not 'q' in request.GET: initial = {} if request.session.get('nickname', None): initial['q'] = 'friends:%s' % request.session['nickname'] extra_context = { 'form': SearchForm(initial=initial), } return render_to_response('search_form.html', extra_context, context_instance=RequestContext(request)) else: form = SearchForm(request.GET) if not form.is_valid(): extra_context = { 'form': form, } return render_to_response('search_form.html', extra_context, context_instance=RequestContext(request)) if request.session.get('nickname', None): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) else: f = friendfeed.FriendFeed() start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) q = form.data['q'] data = f.search(q, **request_to_feed_args_dict(request)) if 'errorCode' in data: return error(request, data) entries = [entry for entry in data['entries'] if not entry['hidden']] hidden = [entry for entry in data['entries'] if entry['hidden']] extra_context = { 'entries': entries, 'hidden': hidden, 'next': start + num, 'title': q, 'form': form, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('search.html', extra_context, context_instance=RequestContext(request))
def rooms(request): '''Display the authenticated users rooms page or a list of the users rooms Authentication is required. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) if 'list' in request.GET: data = f.fetch_user_profile(request.session['nickname']) if not 'errorCode' in data: extra_context = { 'rooms': data['rooms'], } template = 'rooms_list.html' else: start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) data = f.fetch_rooms_feed(**request_to_feed_args_dict(request)) if not 'errorCode' in data: entries = [entry for entry in data['entries'] if not entry['hidden']] hidden = [entry for entry in data['entries'] if entry['hidden']] extra_context = { 'entries': entries, 'hidden': hidden, 'next': start + num, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) template = 'rooms.html' if 'errorCode' in data: return error(request, data) return render_to_response(template, extra_context, context_instance=RequestContext(request))
def entry(request, entry): '''View a single entry. entry is the entry id. ''' if request.session.get('nickname', None): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) else: f = friendfeed.FriendFeed() data = f.fetch_entry(entry) if 'errorCode' in data: return error(request, data) extra_context = { 'entries': data['entries'], 'permalink': True, 'title': data['entries'][0]['title'], } return render_to_response('entry.html', extra_context, context_instance=RequestContext(request))
def related(request): url = request.GET.get('url', None) if not url: raise Http404 if request.session.get('nickname', None): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) else: f = friendfeed.FriendFeed() start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) data = f.fetch_url_feed(url, **request_to_feed_args_dict(request)) if 'errorCode' in data: return error(request, data) extra_context = { 'entries': data['entries'], 'next': start + num, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('related.html', extra_context, context_instance=RequestContext(request))
def lists(request): '''Display the authenticated users lists Authentication is required. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.fetch_user_profile(request.session['nickname']) if 'errorCode' in data: return error(request, data) extra_context = { 'lists': data['lists'], } return render_to_response('lists.html', extra_context, context_instance=RequestContext(request))
def entry_comment(request, entry): '''Comment on an entry. Authentication is required. entry is the entry id. An optional parameter, comment, in the GET dict will allow you to edit an entry. An optional parameter, body, in the GET dict will initialize the form. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) if request.method == 'POST': form = CommentForm(request.POST) if form.is_valid(): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) if form.data['comment']: data = f.edit_comment(form.data['entry'], form.data['comment'], form.data['body']) else: data = f.add_comment(form.data['entry'], form.data['body'], via=VIA) if 'errorCode' in data: return error(request, data) next = form.data['next'] comment = data['id'] args = { 'entry': form.data['entry'], 'comment': comment, 'message': 'edited' if form.data['comment'] else 'commented', } next += '?%s#%s' % (urllib.urlencode(args), comment) return HttpResponseRedirect(next) else: initial = { 'body': request.GET.get('body', None), 'comment': request.GET.get('comment', None), 'entry': entry, 'next': reverse('entry', args=[entry]), } form = CommentForm(initial=initial) extra_context = { 'form': form, } return render_to_response('comment.html', extra_context, context_instance=RequestContext(request))
def login(request): '''Log a user in. ''' extra_context = {} if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): nickname = form.data['nickname'].strip().lower() f = friendfeed.FriendFeed(nickname, form.data['key']) data = f.validate() if 'errorCode' in data: return error(request, data) request.session['nickname'] = nickname request.session['key'] = form.data['key'] return HttpResponseRedirect('/?message=settings') else: form = LoginForm() extra_context['form'] = form return render_to_response('login.html', extra_context, context_instance = RequestContext(request))
def user_unsubscribe(request, nickname): '''Unsubscribe to a user. Authentication is required. ''' if not request.method == 'POST': return HttpResponseRedirect(reverse('user', args=[nickname])) if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.user_unsubscribe(nickname) if 'errorCode' in data: return error(request, data) memcache.delete('profile/' + request.session['nickname']) args = { 'message': data.get('status', '') } return HttpResponseRedirect(reverse('user', args=[nickname]) + '?' + urllib.urlencode(args))
def entry_unlike(request, entry): '''Un-like an entry. Authentication is required. entry is the entry id to be un-liked. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.delete_like(entry) if 'errorCode' in data: return error(request, data) next = reverse('entry', args=[entry]) args = { 'message': 'un-liked', 'entry': entry, } next += '?%s#%s' % (urllib.urlencode(args), entry) return HttpResponseRedirect(next)
def entry_hide(request, entry): '''Hide an entry. Authentication is required. entry is the entry id to be hidden. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.hide_entry(entry) if 'errorCode' in data: return error(request, data) next = request.GET.get('next', '/') args = { 'message': 'hidden', 'entry': entry, } next += '?%s#%s' % (urllib.urlencode(args), entry) return HttpResponseRedirect(next)
def home(request): '''Render a users home feed. Authentication is required. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) data = f.fetch_home_feed(**request_to_feed_args_dict(request)) if 'errorCode' in data: return error(request, data) entries = [entry for entry in data['entries'] if not entry['hidden']] hidden = [entry for entry in data['entries'] if entry['hidden']] new_start = start while len(entries) < num and (new_start - start) / num < 3: new_start = new_start + num kwargs = request_to_feed_args_dict(request) kwargs['start'] = new_start data = f.fetch_home_feed(**kwargs) if 'errorCode' in data: break more_entries = [entry for entry in data['entries'] if not entry['hidden']] more_hidden = [entry for entry in data['entries'] if entry['hidden']] entries.extend(more_entries) hidden.extend(more_hidden) entries = entries[:num] extra_context = { 'entries': entries, 'next': start + len(entries) + len(hidden), 'hidden': hidden, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('home.html', extra_context, context_instance=RequestContext(request))
def share(request): '''Publish a message to the users feed or a room (if 'room' is set in the POST dict. Authentication is required. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) if request.method == 'POST': if 'title' in request.POST: data = f.publish_message(request.POST['title'], via=VIA, room=request.POST.get('room', None)) if 'errorCode' in data: return error(request, data) next = reverse('entry', args=[data['entries'][0]['id']]) args = { 'message': 'shared', 'entry': data['entries'][0]['id'], } next += '?%s#%s' % (urllib.urlencode(args), data['entries'][0]['id']) return HttpResponseRedirect(next)
def public(request): ''' Render the public feed. Authentication is not required and not used. Memcache saves this data so we don't have to hit FriendFeed as often for it. ''' f = friendfeed.FriendFeed() start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) data = f.fetch_public_feed(**request_to_feed_args_dict(request)) if 'errorCode' in data: return error(request, data) entries = data['entries'] extra_context = { 'entries': entries, 'next': start + num, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('public.html', extra_context, context_instance=RequestContext(request))
def entry_delete(request, entry): '''Delete an entry. Authentication is required. entry is the entry id. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.delete_entry(entry) if 'errorCode' in data: return error(request, data) next = request.GET.get('next', '/') if next == reverse('entry', args=[entry]): next = '/' args = { 'message': 'deleted', 'entry': entry, } next += '?%s' % (urllib.urlencode(args)) return HttpResponseRedirect(next)
def comment_delete(request, entry, comment): '''Delete a comment. Authentication is required. entry is the entry id. comment is the comment id. ''' if not request.session.get('nickname', None): return HttpResponseRedirect(reverse('login')) f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) data = f.delete_comment(entry, comment) if 'errorCode' in data: return error(request, data) next = reverse('entry', args=[entry]) args = { 'message': 'deleted', 'entry': entry, 'comment': comment, } next += '?%s#%s' % (urllib.urlencode(args), entry) return HttpResponseRedirect(next)
def fetch(load_picklepath=None, save_picklepath=None): try: import friendfeed except ImportError: logger.error("Aborting fetch: unable to import friendfeed api.") return if not hasattr(settings, 'CONSONANCE_USERS'): logger.error( "Aborting fetch: settings.CONSONANCE_USERS is undefined or empty.") return logger.info("Commencing fetch for %s users." % settings.CONSONANCE_USERS.__len__()) api = friendfeed.FriendFeed() if (settings.CONSONANCE_USERS.__len__() > 1) and (load_picklepath or save_picklepath): logger.critical( "The mock/pickle data functionality cannot work with multiple users in CONSONANCE_USERS. Aborting..." ) return for user in settings.CONSONANCE_USERS.keys(): if load_picklepath: logger.debug("Attempting to use pickle data file at %s" % load_picklepath) try: try: import pickle load_picklefile = open(load_picklepath, 'rb') raw = pickle.load(load_picklefile) except: handle_exception( user, "attempted to use pickled data but failed.") continue else: logger.info( "Using pickled data from file, not accessing FriendFeed!" ) finally: load_picklefile.close() else: try: raw = api.fetch_user_feed(user) except: handle_exception(user, "failed to fetch activity") continue if not raw['entries']: logger.info('No activity available for user "%s".' % user) continue if save_picklepath: try: try: import pickle save_picklefile = open(save_picklepath, 'wb') pickle.dump(raw, save_picklefile) except: handle_exception(user, "failed to save pickle data") continue else: logger.info( "Successfully saved FriendFeed activity to pickle file %s" % save_picklepath) finally: save_picklefile.close() processed_ok = 0 processed_skip = 0 processed_fail = 0 for entry in raw['entries']: try: if process_entry(entry, settings.CONSONANCE_USERS[user]): processed_ok += 1 else: processed_skip += 1 except: handle_exception(user, "failed to process entry") processed_fail += 1 continue logger.info('Fetch complete. Processed %i OK / %i Skipped / %i Failed.' % (processed_ok, processed_skip, processed_fail))
def user(request, nickname, type=None): '''Render a users feed. Authentication is not required but is used if set. nickname is the user's nickname. type can be None (default), 'comments', 'likes', 'discussion', or 'friends' ''' if request.session.get('nickname', None): f = friendfeed.FriendFeed(request.session['nickname'], request.session['key']) key = 'profile/' + request.session['nickname'] current_user = memcache.get(key) if not current_user: current_user = {} try: current_user = f.fetch_user_profile(request.session['nickname']) memcache.set(key, current_user, 60*60) except: pass subscriptions = [s['nickname'] for s in current_user.get('subscriptions', [])] subscribed = nickname in subscriptions else: f = friendfeed.FriendFeed() subscribed = False start = max(get_integer_argument(request, 'start', 0), 0) num = get_integer_argument(request, 'num', NUM) kwargs = request_to_feed_args_dict(request) if type == 'comments': data = f.fetch_user_comments_feed(nickname, **kwargs) elif type == 'likes': data = f.fetch_user_likes_feed(nickname, **kwargs) elif type == 'discussion': data = f.fetch_user_discussion_feed(nickname, **kwargs) elif type == 'friends': data = f.fetch_user_friends_feed(nickname, **kwargs) else: data = f.fetch_user_feed(nickname, **kwargs) try: profile = f.fetch_user_profile(nickname) except: profile = { 'name': data['entries'][0]['user']['name'], } if 'errorCode' in data: return error(request, data) entries = [entry for entry in data['entries'] if not entry['hidden']] hidden = [entry for entry in data['entries'] if entry['hidden']] extra_context = { 'entries': entries, 'hidden': hidden, 'next': start + num, 'profile': profile, 'subscribed': subscribed, 'type': type, } if start > 0: extra_context['has_previous'] = True extra_context['previous'] = max(start - num, 0) if request.GET.get('output', 'html') == 'atom': return atom(entries) return render_to_response('user.html', extra_context, context_instance=RequestContext(request))