digrsser / app / digrsser /

Full commit
# -*- coding: utf-8 -*-
The views building logic are implemented in this file.
The routes leading to the views are defined in
import logging

from google.appengine.api import users

import flask
from flask import abort
from flask import render_template
from flask import redirect
from flask import request
from flask import flash
from flask import url_for
from flask import make_response
import jinja2

from digrsser.application import app

from digrsser.decorators import login_required, admin_required, do_logout
from digrsser.secret_keys import SESSION_KEY
from digrsser import forms
from digrsser.models import Digrsser, Subscription, FeedEntry, FeedGroupingRule, Subscriber, Key

def main():
  # Check if installed and no grouping roles exists
  if not FeedGroupingRule.all().count():
    return redirect(url_for('install'))

  # Show the startup/subscription page based on user
  if users.get_current_user():
    return redirect(url_for('list_subs'))
    return render_template('welcome.html', name='private')

def cache(engine='gae', param=None):
  Only for testing purposes
  cache = None'Using %s engine' % engine)

  if engine == 'gae':
    from werkzeug.contrib.cache import GAEMemcachedCache as Cache
    cache = Cache(default_timeout=60)
  if engine == 'ext':
    from flaskext.cache import Cache
    cache = Cache(app)
  if engine == 'sdk':
    from google.appengine.api import memcache as cache

  if cache:
    key = '%skey' % engine
    data = cache.get(key)
    if not data:
      data = '%svalue' % engine
      logging.warning('setting data to %s: %s' % (engine, data))
      cache.set(key, data)
    else:'using cached value: %s' % data)

    return make_response('cache test completed: %s:%s' % (engine, param))

  return abort(404)

def install():
  Runs the installation steps
  for new app. Requires admin privileges.
  # Do the installation
  if request.method == 'POST':
    # Generate default grouping rules
    rules = [
      {'name': '1 hour', 'interval':1, 'count':''},
      {'name': '6 hours', 'interval':6, 'count':''},
      {'name': '12 hours', 'interval':12, 'count':''},
      {'name': '1 day', 'interval':24, 'count':''},
      {'name': '2 days', 'interval':48, 'count':''},
      {'name': '5 days', 'interval':120, 'count':''},
      {'name': '7 hours', 'interval':168, 'count':''},
      {'name': '12 hours or 5 entries', 'interval':168, 'count':5},
      {'name': '2 entries', 'interval':'', 'count':2},
    counter = 0
    for rule in rules:
      name = rule['name']
      count = int(rule['count']) if rule['count'] else None
      interval = int(rule['interval']) if rule['interval'] else None

      # Check if the rule already exists with the name: if not, create it
      grule = FeedGroupingRule.all().filter('title =', name)
      #print grule.count()

      if not grule.count():
        logging.debug('no rule')
        fgr = FeedGroupingRule(title=name, interval=interval, count=count)
        counter += 1

    flash('Installation completed (%d rules created)' % counter)
    return redirect(url_for('main'))

  # Show the installation confirmation
  setup_form = forms.SetupForm(request.form)

  return render_template('install.html', form=setup_form)

def uninstall():
  Delete all the content

  .. NOTE:: Testing purposes only

  flash('Uninstallation completed')

  return redirect(url_for('main'))

def admin():
  Redirects to appengine admin page
  if app.config['DEBUG_MODE']:
    return redirect('/_ah/admin')
  return redirect('')

def logout():
  return redirect('/')

def show_feed():
  baker = Digrsser()
  feeds = baker.subscribe('')
  return str(feeds)

def list_subs():
  List the subscriptions
  # If the request path is /sub, the redirect to /sub/list
  if request.path.split('/')[-1] == 'sub':
    return redirect(url_for('list_subs'))
  return render_template('list_subs.html')

def edit_sub(id):
  Show details of the selected subscription
  and allows to modify it
  usb = Subscriber.get_current()
  sub = Subscription.get_by_userid(id)

  if not sub:
    flash('Subscription %d cannot be found ' % id)
    return redirect(url_for('subscriptions'))

  form = forms.SubscriptionForm(request.form)

  # Handle form submit
  if request.method == 'POST':

    # Cancel the action
      flash('Cancelled by the user')
      return redirect(url_for('list_subs'))

    sub.title =
    sub.urls = []
    sub.grouping_rule = FeedGroupingRule.get_by_id(long(

    flash('Updated subscription')
    return redirect(url_for('edit_sub', id=id))

  # Fill form values = sub.key().id() = sub.title = sub.urls[0] = sub.grouping_rule.key().id()

  return render_template('edit_sub.html', form=form, sub=sub)

def add_sub():
  Creates new subscription with following POST


      URL to fetch
      Grouping rule id
  form = forms.SubscriptionForm(request.form)

  # If the view was requested, show the page with form
  # otherwise handle the post
  if request.method == 'GET':
    return make_response(render_template('add_sub.html', form=form))

  # Cancel the action
    flash('Cancelled by the user')
    return redirect(url_for('list_subs'))

  # Run validation does not pass, return back (form contains the errors)
  if not form.validate():
    return make_response(render_template('add_sub.html', form=form))

  subscriber = Subscriber.get_current()
    urls = []
    rule = FeedGroupingRule.get_by_id(long('Rule: %s Urls: %s' % (rule, urls))

    sub = Subscription(subscriber=subscriber, urls=urls, grouping_rule=rule)
    flash('URL subscribed')

    # Try retrieving the data right away
    dig = Digrsser(sub)
    count = len(dig.fetch(10))

    # Try to get the name for the subscription
    if not sub.title:
      sub.title = dig.get_title() or sub.urls[0]

    if count:
      flash('Retrieved %d entries' % count)
      flash('No entries found - please check the URL', 'warning')

  except Exception, ex:
    logging.error('Failed to add URL: %s' % ex)
    flash('Failed to add URL', 'error')

  return redirect(url_for('list_subs'))

def show_sub_feed(id):
  sub = Subscription.get_by_userid(id)
  entries = FeedEntry.all().filter('subscription = ', sub)

  return render_template('feed.html', entries=entries)

def show_sub_rss(key):
  Show the feed contents of subscription (based on given Subscription key)
  in XML (RSS) format

  .. NOTE::

     This URL does not require any authentication (easier for the RSS readers)
     and therefore the path is constructed using Subscription key - making it
     somewhat harder to guess

  # Load subscription directly using the given key
  sub = Subscription.get(key)

  if not sub:
    return flask.abort(404)

  groups = sub.get_closed_groups()

  # Provide the escape function to view
  escape = jinja2.escape

  response = make_response(render_template('base.xml', subscription=sub, groups=groups, escape=escape))
  response.headers['Content-Type'] = 'application/rss+xml'

  return response

def update_sub(id):
  Fetches the possible feed updates for the subscription and updates
  the entries to database
  sub = Subscription.get_by_userid(id)
  sgt = Digrsser(sub)
  new_entries = sgt.fetch()

  if not new_entries:
    flash('No updates')
    flash('Updated %d entries' % len(new_entries))

  return redirect(url_for('list_subs'))

def del_sub(id):
  Remove the subscription pointed by id
  sub = Subscription.get_by_userid(id)
  if sub:
    urls = sub.urls
    flash('Removed %s' % ', '.join(urls))
    flash('Failed to remove %s' % id, 'warning')

  return redirect(url_for('list_subs'))

def show_messages():
  Makes an ajax-compatible responses
  from requested paths
  msghtml = render_template('message.html')
  return msghtml

def ajax_sub_entries(id):
  Returns HTML list of feed entries
  from the selected subscription
  sub = Subscription.get_by_userid(id)

  #entries = FeedEntry.all().filter('subscription = ', sub)
  groups = sub.get_groups()

  return render_template('entries.html', groups=groups)

def inject_usersubs():
  msgs = flask.get_flashed_messages()
  user = users.get_current_user()

  # Form for subscribing
  form = forms.SubscriptionForm(request.form)'form: %s' % form)

  # Get list of subscriptions
  subscriber = Subscriber.get_current()
  subs = list(Subscription.all().filter('subscriber = ', subscriber))
  rules = FeedGroupingRule.all()

  is_admin = users.is_current_user_admin()

  return dict(

def get_hashkey(key):
    Returns the salted key, with length of 40 characters
    import base64
    import hashlib
    return base64.b64encode( + key))