From 0f80fc74a0ec97e75ba4a45c437dec0d7898ed95 Mon Sep 17 00:00:00 2001
From: codl
Date: Tue, 1 Aug 2017 20:57:15 +0200
Subject: [PATCH] RESPONSIBILTIY'S COOL
---
lib/__init__.py | 2 ++
lib/interval.py | 50 ++++++++++++++++++++++++++++
migrations/versions/9fab742962ef_.py | 32 ++++++++++++++++++
model.py | 16 ++++++---
routes.py | 16 ++++++---
tasks.py | 9 +++++
templates/lib/interval.html | 15 +++++++++
templates/settings.html | 22 ++++++------
8 files changed, 142 insertions(+), 20 deletions(-)
create mode 100644 lib/interval.py
create mode 100644 migrations/versions/9fab742962ef_.py
create mode 100644 templates/lib/interval.html
diff --git a/lib/__init__.py b/lib/__init__.py
index 96e2497..4b0da44 100644
--- a/lib/__init__.py
+++ b/lib/__init__.py
@@ -1 +1,3 @@
from .auth import require_auth
+from .interval import decompose_interval
+from .interval import SCALES as interval_scales
diff --git a/lib/interval.py b/lib/interval.py
new file mode 100644
index 0000000..e222650
--- /dev/null
+++ b/lib/interval.py
@@ -0,0 +1,50 @@
+from datetime import timedelta
+
+SCALES = [
+ ('seconds', timedelta(seconds=1)),
+ ('minutes', timedelta(minutes=1)),
+ ('hours', timedelta(hours=1)),
+ ('days', timedelta(days=1)),
+ ('months', timedelta(days=30)),
+ ('years', timedelta(days=365)),
+]
+
+def decompose_interval(attrname):
+ scales = [scale[1] for scale in SCALES]
+ scales.reverse()
+
+ def decorator(cls):
+ scl_name = '{}_scale'.format(attrname)
+ sig_name = '{}_significand'.format(attrname)
+
+ @property
+ def scale(self):
+ for m in scales:
+ if getattr(self, attrname) % m == timedelta(0):
+ return m
+
+ return timedelta(seconds=1)
+
+ @scale.setter
+ def scale(self, value):
+ print(value)
+ if(type(value) != timedelta):
+ value = timedelta(seconds=float(value))
+ print(value)
+ setattr(self, attrname, getattr(self, sig_name) * value)
+
+ @property
+ def significand(self):
+ return int(getattr(self, attrname) / getattr(self, scl_name))
+
+ @significand.setter
+ def significand(self, value):
+ setattr(self, attrname, int(value) * getattr(self, scl_name))
+
+
+ setattr(cls, scl_name, scale)
+ setattr(cls, sig_name, significand)
+
+ return cls
+
+ return decorator
diff --git a/migrations/versions/9fab742962ef_.py b/migrations/versions/9fab742962ef_.py
new file mode 100644
index 0000000..af79f73
--- /dev/null
+++ b/migrations/versions/9fab742962ef_.py
@@ -0,0 +1,32 @@
+"""empty message
+
+Revision ID: 9fab742962ef
+Revises: 711770097f06
+Create Date: 2017-08-01 00:33:59.183437
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '9fab742962ef'
+down_revision = '711770097f06'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('accounts', sa.Column('policy_delete_every', sa.Interval(), server_default='0', nullable=True))
+ op.add_column('accounts', sa.Column('policy_keep_latest', sa.Integer(), server_default='0', nullable=True))
+ op.add_column('accounts', sa.Column('policy_keep_younger', sa.Interval(), server_default='0', nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('accounts', 'policy_keep_younger')
+ op.drop_column('accounts', 'policy_keep_latest')
+ op.drop_column('accounts', 'policy_delete_every')
+ # ### end Alembic commands ###
diff --git a/model.py b/model.py
index fc64403..e59263b 100644
--- a/model.py
+++ b/model.py
@@ -4,6 +4,7 @@ from app import db
from twitter import Twitter, OAuth
import secrets
+from lib import decompose_interval
class TimestampMixin(object):
created_at = db.Column(db.DateTime, server_default=db.func.now())
@@ -33,15 +34,17 @@ class RemoteIDMixin(object):
-class Account(db.Model, TimestampMixin, RemoteIDMixin):
+@decompose_interval('policy_delete_every')
+@decompose_interval('policy_keep_younger')
+class Account(TimestampMixin, RemoteIDMixin):
__tablename__ = 'accounts'
id = db.Column(db.String, primary_key=True)
policy_enabled = db.Column(db.Boolean, server_default='FALSE', nullable=False)
- # policy_keep_younger = db.Column(db.Interval)
- # policy_keep_latest = db.Column(db.Integer)
- # policy_delete_every = db.Column(db.Interval)
+ policy_keep_latest = db.Column(db.Integer, server_default='0')
policy_ignore_favourites = db.Column(db.Boolean, server_default='TRUE')
+ policy_delete_every = db.Column(db.Interval, server_default='0', default=0)
+ policy_keep_younger = db.Column(db.Interval, server_default='0', default=0)
remote_display_name = db.Column(db.String)
remote_screen_name = db.Column(db.String)
@@ -61,6 +64,11 @@ class Account(db.Model, TimestampMixin, RemoteIDMixin):
def post_count(self):
return Post.query.filter(Post.author_id == self.id).count()
+
+class Account(Account, db.Model):
+ pass
+
+
class OAuthToken(db.Model, TimestampMixin):
__tablename__ = 'oauth_tokens'
diff --git a/routes.py b/routes.py
index 2f22d40..12ec85b 100644
--- a/routes.py
+++ b/routes.py
@@ -2,6 +2,7 @@ from app import app
from flask import render_template, url_for, redirect, request, g, Response
from datetime import datetime
import lib.twitter
+import lib
from lib import require_auth
from model import Account, Session, Post, TwitterArchive
from app import db
@@ -46,7 +47,7 @@ def twitter_login_step2():
db.session.add(session)
db.session.commit()
- tasks.fetch_acc.s(token.account_id).delay()
+ tasks.fetch_acc.s(token.account_id).apply_async(routing_key='high')
resp = Response(status=302, headers={"location": url_for('index')})
resp.set_cookie('forget_sid', session.id,
@@ -63,7 +64,7 @@ def upload_tweet_archive():
db.session.add(ta)
db.session.commit()
- tasks.import_twitter_archive.s(ta.id).apply_async()
+ tasks.import_twitter_archive.s(ta.id).apply_async(routing_key='high')
return render_template('upload_tweet_archive.html')
@@ -71,13 +72,20 @@ def upload_tweet_archive():
@require_auth
def settings():
if request.method == 'POST':
- for attr in ('policy_enabled', 'policy_ignore_favourites'):
+ for attr in ('policy_enabled',
+ 'policy_ignore_favourites',
+ 'policy_keep_latest',
+ 'policy_delete_every_significand',
+ 'policy_delete_every_scale',
+ 'policy_keep_younger_significand',
+ 'policy_keep_younger_scale',
+ ):
if attr in request.form:
setattr(g.viewer.account, attr, request.form[attr])
db.session.commit()
- return render_template('settings.html')
+ return render_template('settings.html', scales=lib.interval_scales)
diff --git a/tasks.py b/tasks.py
index 92083f0..2a7f0ce 100644
--- a/tasks.py
+++ b/tasks.py
@@ -10,8 +10,17 @@ from datetime import timedelta, datetime
from zipfile import ZipFile
from io import BytesIO, TextIOWrapper
import json
+from kombu import Queue
app = Celery('tasks', broker=flaskapp.config['CELERY_BROKER'], task_serializer='pickle')
+app.conf.task_queues = (
+ Queue('default', routing_key='celery'),
+ Queue('high_prio', routing_key='high'),
+ Queue('higher_prio', routing_key='higher'),
+)
+app.conf.task_default_queue = 'default'
+app.conf.task_default_exchange = 'celery'
+app.conf.task_default_exchange_type = 'direct'
@app.task(autoretry_for=(TwitterError, URLError))
def fetch_acc(id, cursor=None):
diff --git a/templates/lib/interval.html b/templates/lib/interval.html
new file mode 100644
index 0000000..18e709c
--- /dev/null
+++ b/templates/lib/interval.html
@@ -0,0 +1,15 @@
+{% macro interval_input(obj, attrname, scales) -%}
+
+
+
+
+
+{%- endmacro %}
diff --git a/templates/settings.html b/templates/settings.html
index c935f64..36d4c19 100644
--- a/templates/settings.html
+++ b/templates/settings.html
@@ -9,21 +9,19 @@
- {#
+ {%- from 'lib/interval.html' import interval_input %}
+ Delete one post every
+ {{interval_input(g.viewer.account, 'policy_delete_every', scales)}}
+
Keep posts less than
-
-
+ {{interval_input(g.viewer.account, 'policy_keep_younger', scales)}}
old
- #}
- Keep posts that you have favourited:
+
Keep my
+
+ latest posts
+
+ Keep posts that I have favourited