diff --git a/woodwind/models.py b/woodwind/models.py index 2535e2b..a74ebb8 100644 --- a/woodwind/models.py +++ b/woodwind/models.py @@ -99,7 +99,9 @@ class Subscription(db.Model): # user-editable name of this subscribed feed name = db.Column(db.String(256)) tags = db.Column(db.String(256)) - + # exclude from the front page + exclude = db.Column(db.Boolean, default=False) + user = db.relationship(User, backref='subscriptions') feed = db.relationship(Feed, backref='subscriptions') diff --git a/woodwind/static/feed.js b/woodwind/static/feed.js index b7b1288..54b71f0 100644 --- a/woodwind/static/feed.js +++ b/woodwind/static/feed.js @@ -64,15 +64,16 @@ $(function(){ function attachListeners() { $("#older-link").off('click').click(clickOlderLink); $(".micropub-form button[type='submit']").off('click').click(submitMicropubForm); - $(".reply-area").hide(); + $(".reply-area.closed").hide(); $("article").off('click').click(function(evt) { var $target = $(evt.target); if ($target.closest("form, a, video, audio").length == 0) { + + $(".reply-area", this).toggleClass("closed"); $(".reply-area", this).slideToggle(200); } }); - } diff --git a/woodwind/static/style.css b/woodwind/static/style.css index 74109bd..de7eb88 100644 --- a/woodwind/static/style.css +++ b/woodwind/static/style.css @@ -360,7 +360,8 @@ th { /* Subtlety of Hue */ body { font: 12pt Helvetica, Arial, sans-serif; - background: #ecebf0; + /*background: $athens-gray;*/ + background: #f4f4f4; padding-top: 1em; } a { @@ -410,12 +411,13 @@ ul#navigation { article { margin-bottom: 2em; - box-shadow: 0 0 2px #687d77; - background-color: white; + /*box-shadow: $box-shadow; + background-color: white;*/ padding: 0.5em; } article.reply-context { margin-bottom: 0; - background-color: #f3f3f3; } + background-color: #e0e0e0; + color: #555; } article.reply-context .content img { max-height: 240px; max-width: 240px; } diff --git a/woodwind/static/style.scss b/woodwind/static/style.scss index 201bff5..deef439 100644 --- a/woodwind/static/style.scss +++ b/woodwind/static/style.scss @@ -17,7 +17,8 @@ $box-shadow: 0 0 2px $sirocco; body { font: 12pt $body-font; - background: $athens-gray; + /*background: $athens-gray;*/ + background: #f4f4f4; padding-top: 1em; } @@ -86,13 +87,14 @@ ul#navigation { article { margin-bottom: 2em; - box-shadow: $box-shadow; - background-color: white; + /*box-shadow: $box-shadow; + background-color: white;*/ padding: 0.5em; &.reply-context { margin-bottom: 0; - background-color: #f3f3f3; + background-color: #e0e0e0; + color: #555; .content img { max-height: 240px; max-width: 240px; @@ -246,10 +248,10 @@ button { .reply-area { text-align: center; margin-top: 0.5em; - + .content { height: 4em; - } + } .reply-link { display: inline-block; diff --git a/woodwind/static/subscriptions.js b/woodwind/static/subscriptions.js index 8207c7e..497dc69 100644 --- a/woodwind/static/subscriptions.js +++ b/woodwind/static/subscriptions.js @@ -18,8 +18,20 @@ $(function() { }).fail(function failure() { $(".save-status", form).html("Save Failed!"); }); + }); + $("form.poll-now").submit(function(evt) { + var form = $(this); + evt.preventDefault(); + $(".poll-status", form).html(""); + + $.post(form.attr('action'), form.serialize(), function success(){ + $(".poll-status", form).html("Poll Requested."); + }).fail(function failure() { + $(".poll-status", form).html("Polling Failed!"); + }); + }); }); diff --git a/woodwind/tasks.py b/woodwind/tasks.py index 8fda8b1..49e1a14 100644 --- a/woodwind/tasks.py +++ b/woodwind/tasks.py @@ -311,8 +311,13 @@ def notify_feed_updated(app, feed_id, entry_ids): 'subscription': s.id, 'entries': rendered, }) - for topic in ('user:{}'.format(s.user.id), - 'subsc:{}'.format(s.id)): + + topics = [] + if not s.exclude: + topics.append('user:{}'.format(s.user.id)) + topics.append('subsc:{}'.format(s.id)) + + for topic in topics: redis.publish('woodwind_notify:{}'.format(topic), message) diff --git a/woodwind/templates/_entry.jinja2 b/woodwind/templates/_entry.jinja2 index d728454..d4ff5b8 100644 --- a/woodwind/templates/_entry.jinja2 +++ b/woodwind/templates/_entry.jinja2 @@ -73,7 +73,7 @@ | {% for synd in entry.get_property('syndication') %} {{ synd | domain_for_url}}{% endfor %} {% endif %} -
- - diff --git a/woodwind/views.py b/woodwind/views.py index 47afdf9..6e24556 100644 --- a/woodwind/views.py +++ b/woodwind/views.py @@ -2,7 +2,8 @@ from . import tasks, util from .extensions import db, login_mgr, micropub from .models import Feed, Entry, User, Subscription import flask.ext.login as flask_login -import binascii + +import base64 import bs4 import datetime import feedparser @@ -74,6 +75,7 @@ def index(): entry_query = entry_query.filter( sqlalchemy.sql.expression.cast(Entry.properties['jam'], sqlalchemy.TEXT) == 'true') else: + entry_query = entry_query.filter(Subscription.exclude == False) ws_topic = 'user:{}'.format(flask_login.current_user.id) entry_query = entry_query.order_by(Entry.retrieved.desc(), @@ -226,6 +228,7 @@ def edit_subscription(): subsc.tags = ' '.join(t.strip() for t in tag_list if t.strip()) else: subsc.tags = None + subsc.exclude = flask.request.form.get('exclude') == 'true' db.session.commit() flask.flash('Edited {}'.format(subsc.name)) @@ -609,13 +612,29 @@ def add_preview(content): @views.app_template_filter() def proxy_image(url): + proxy_url = flask.current_app.config.get('IMAGEPROXY_URL') + proxy_key = flask.current_app.config.get('IMAGEPROXY_KEY') + if proxy_url and proxy_key: + sig = base64.urlsafe_b64encode( + hmac.new(proxy_key.encode(), url.encode(), hashlib.sha256).digest() + ).decode() + return '/'.join((proxy_url.rstrip('/'), 's' + sig, url)) + + pilbox_url = flask.current_app.config.get('PILBOX_URL') + pilbox_key = flask.current_app.config.get('PILBOX_KEY') + if pilbox_url and pilbox_key: + query = urllib.parse.urlencode({'url': url, 'op': 'noop'}) + sig = hmac.new(pilbox_key.encode(), query.encode(), hashlib.sha1).hexdigest() + query += '&sig=' + sig + return pilbox_url + '?' + query + camo_url = flask.current_app.config.get('CAMO_URL') camo_key = flask.current_app.config.get('CAMO_KEY') - if not camo_url or not camo_key: - return url - digest = hmac.new(camo_key.encode(), url.encode(), hashlib.sha1).hexdigest() - return (urllib.parse.urljoin(camo_url, digest) - + '?url=' + urllib.parse.quote_plus(url)) + if camo_url and camo_key: + digest = hmac.new(camo_key.encode(), url.encode(), hashlib.sha1).hexdigest() + return (urllib.parse.urljoin(camo_url, digest) + + '?url=' + urllib.parse.quote_plus(url)) + return url @views.app_template_filter()