query individual feeds by their url rather than id

prevent nefarious people like @dissolve from crawling all the
subscribed feeds :P
This commit is contained in:
Kyle Mahan 2015-02-09 22:46:02 -08:00
parent 19180b1829
commit 32cdeaa781
8 changed files with 42 additions and 23 deletions

3
fabfile.py vendored
View file

@ -24,8 +24,7 @@ def restart():
with cd(REMOTE_PATH):
with prefix("source venv/bin/activate"):
run("pip install -r requirements.txt")
# run("uwsgi --reload /tmp/redwind.pid")
run("supervisorctl restart woodwind woodwind-celery")
run("supervisorctl restart ww:*")
def deploy():

View file

@ -1,5 +1,6 @@
import bleach
import json
import binascii
from .extensions import db
@ -85,6 +86,9 @@ class Feed(db.Model):
last_checked = db.Column(db.DateTime)
etag = db.Column(db.String(512))
def get_feed_code(self):
return binascii.hexlify(self.feed.encode())
def __repr__(self):
return '<Feed:{},{}>'.format(self.name, self.feed)

View file

@ -403,6 +403,8 @@ article {
article header img {
max-width: 64px;
max-height: 64px;
min-width: 48px;
min-height: 48px;
margin-left: -85px;
float: left;
border-radius: 4px; }
@ -454,6 +456,8 @@ form {
margin: inherit;
display: inline;
max-width: 1.2em;
max-height: 1.2em; } }
max-height: 1.2em;
min-width: inherit;
min-height: inherit; } }
/*# sourceMappingURL=style.css.map */

View file

@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "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",
"mappings": "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",
"sources": ["normalize.scss","style.scss"],
"names": [],
"file": "style.css"

View file

@ -70,6 +70,8 @@ article {
img {
max-width: 64px;
max-height: 64px;
min-width: 48px;
min-height: 48px;
margin-left: -85px;
float: left;
border-radius: 4px;
@ -144,6 +146,8 @@ form {
display: inline;
max-width: 1.2em;
max-height: 1.2em;
min-width: inherit;
min-height: inherit;
}
}
}

View file

@ -56,7 +56,7 @@ def update_feed(feed_id):
logger.info('Updating {}'.format(feed))
process_feed_for_new_entries(session, feed)
def process_feed_for_new_entries(session, feed):
now = datetime.datetime.utcnow()
found_new = False
@ -76,17 +76,17 @@ def process_feed_for_new_entries(session, feed):
if not old or not is_content_equal(old, entry):
# set a default value for published if none is provided
if not entry.published:
entry.published = (old.published or now) if old else now
entry.published = (old and old.published) or now
if old:
feed.entries.remove(old)
session.delete(old)
feed.entries.append(entry)
session.commit()
found_new = True
else:
logger.info('skipping previously seen post {}'.format(old.permalink))
logger.info('skipping previously seen post %s', old.permalink)
finally:
feed.last_checked = now
@ -104,7 +104,7 @@ def is_content_equal(e1, e2):
and e1.author_name == e2.author_name
and e1.author_url == e2.author_url
and e1.author_photo == e2.author_photo)
def process_xml_feed_for_new_entries(session, feed):
logger.debug('fetching xml feed: %s', feed)
@ -128,7 +128,7 @@ def process_xml_feed_for_new_entries(session, feed):
if 'updated_parsed' in p_entry:
updated = datetime.datetime.fromtimestamp(
time.mktime(p_entry.updated_parsed))
time.mktime(p_entry.updated_parsed))
else:
updated = None
@ -203,7 +203,8 @@ def process_html_feed_for_new_entries(session, feed):
title=title,
content=content,
author_name=hentry.get('author', {}).get('name'),
author_photo=hentry.get('author', {}).get('photo') or fallback_photo(feed.origin),
author_photo=hentry.get('author', {}).get('photo')
or fallback_photo(feed.origin),
author_url=hentry.get('author', {}).get('url'))
logger.debug('built entry: %s', entry.permalink)

View file

@ -13,10 +13,10 @@
action="{{ url_for('.update_all') }}" method="POST">
<button type="submit">Update All</button>
</form>
{% for feed in feeds %}
<article>
<form style="display:inline"
action="{{ url_for('.edit_feed') }}" method="POST">
<input type="hidden" name="id" value="{{ feed.id }}"/>
@ -37,7 +37,7 @@
<button type="submit">Delete</button>
</form>
<br/>
<a href="{{ url_for('.index', feed=feed.id) }}">View posts from this feed</a>
<a href="{{ url_for('.index', feed=feed.get_feed_code()) }}">View posts from this feed</a>
</article>
{% endfor %}

View file

@ -2,6 +2,7 @@ from . import tasks
from .extensions import db, login_mgr, micropub
from .models import Feed, Entry, User
import flask.ext.login as flask_login
import binascii
import bs4
import feedparser
import flask
@ -21,15 +22,19 @@ def index():
if flask_login.current_user.is_authenticated():
per_page = flask.current_app.config.get('PER_PAGE', 30)
offset = (page - 1) * per_page
if 'feed' in flask.request.args:
feed_ids = [int(flask.request.args.get('feed'))]
else:
feed_ids = set(f.id for f in flask_login.current_user.feeds)
entry_query = Entry.query\
.join(Entry.feed)\
.join(Feed.users)\
.filter(User.id == flask_login.current_user.id)
if 'feed' in flask.request.args:
feed_hex = flask.request.args.get('feed').encode()
feed_url = binascii.unhexlify(feed_hex).decode('utf-8')
entry_query = entry_query.filter(Feed.feed == feed_url)
entries = entry_query.order_by(Entry.published.desc())\
.offset(offset).limit(per_page).all()
if feed_ids:
entries = Entry.query.filter(Entry.feed_id.in_(feed_ids))\
.order_by(Entry.published.desc())\
.offset(offset).limit(per_page).all()
return flask.render_template('feed.jinja2', entries=entries, page=page)
@ -312,5 +317,7 @@ def url_for_other_page(page):
"""http://flask.pocoo.org/snippets/44/#URL+Generation+Helper
"""
args = flask.request.view_args.copy()
args.update(flask.request.args)
args['page'] = page
return flask.url_for(flask.request.endpoint, **args)