(screams) the time is nigh

This commit is contained in:
codl 2017-08-03 21:37:00 +02:00
parent 9722dbde26
commit a7e414bae2
No known key found for this signature in database
GPG Key ID: 6CD7C8891ED1233A
6 changed files with 93 additions and 11 deletions

View File

@ -77,6 +77,20 @@ class Account(TimestampMixin, RemoteIDMixin):
def post_count(self): def post_count(self):
return Post.query.with_parent(self).count() return Post.query.with_parent(self).count()
def estimate_eligible_for_delete(self):
"""
this is an estimation because we do not know if favourite status has changed since last time a post was refreshed
and it is unfeasible to refresh every single post every time we need to know how many posts are eligible to delete
"""
latest_n_posts = db.session.query(Post.id).with_parent(self).order_by(db.desc(Post.created_at)).limit(self.policy_keep_latest)
query = Post.query.with_parent(self).\
filter(Post.created_at + self.policy_keep_younger <= db.func.now()).\
filter(~Post.id.in_(latest_n_posts))
if(self.policy_keep_favourites):
query = query.filter_by(favourite = False)
return query.count()
class Account(Account, db.Model): class Account(Account, db.Model):

View File

@ -1,6 +1,6 @@
from app import app from app import app
from flask import render_template, url_for, redirect, request, g, Response from flask import render_template, url_for, redirect, request, g, Response
from datetime import datetime from datetime import datetime, timedelta
import lib.twitter import lib.twitter
import lib import lib
from lib import require_auth from lib import require_auth
@ -101,6 +101,20 @@ def enable():
# i.e. about to instantly delete a lot of posts, # i.e. about to instantly delete a lot of posts,
# or when enabling for the first time (last_delete is >1 year in the past) # or when enabling for the first time (last_delete is >1 year in the past)
risky = False
if not 'confirm' in request.form and not g.viewer.account.policy_enabled:
if g.viewer.account.policy_delete_every == timedelta(0):
approx = g.viewer.account.estimate_eligible_for_delete()
return render_template('warn.html', message=f"""You've set the time between deleting posts to 0. Every post that matches your expiration rules will be deleted within minutes.
{ ("That's about " + str(approx) + " posts.") if approx > 0 else "" }
Go ahead?""")
if g.viewer.account.last_delete < datetime.now() - timedelta(days=365):
return render_template('warn.html', message="""Once you enable Forget, posts that match your expiration rules will be deleted <b>permanently</b>. We can't bring them back. Make sure that you won't miss them.""")
if not g.viewer.account.policy_enabled:
g.viewer.account.last_delete = db.func.now()
g.viewer.account.policy_enabled = True g.viewer.account.policy_enabled = True
db.session.commit() db.session.commit()

View File

@ -106,3 +106,7 @@ body > section > .banner {
.banner form { .banner form {
display: inline; display: inline;
} }
label {
display: inline-block;
}

View File

@ -123,8 +123,8 @@ def delete_from_account(account_id):
filter(~Post.id.in_(latest_n_posts)).\ filter(~Post.id.in_(latest_n_posts)).\
order_by(db.func.random()).limit(100).all() order_by(db.func.random()).limit(100).all()
posts = refresh_account(account_id)
if account.service == 'twitter': if account.service == 'twitter':
posts = lib.twitter.refresh_posts(posts)
eligible = list((post for post in posts if not account.policy_keep_favourites or not post.favourite)) eligible = list((post for post in posts if not account.policy_keep_favourites or not post.favourite))
if eligible: if eligible:
if account.policy_delete_every == timedelta(0): if account.policy_delete_every == timedelta(0):
@ -139,9 +139,39 @@ def delete_from_account(account_id):
db.session.commit() db.session.commit()
def refresh_posts(posts):
posts = list(posts)
if len(posts) == 0:
return []
if posts[0].service == 'twitter':
return lib.twitter.refresh_posts(posts)
@app.task
def refresh_account(account_id):
account = Account.query.get(account_id)
oldest_post = Post.query.with_parent(account).order_by(db.asc(Post.updated_at)).first()
if not oldest_post:
return []
posts = Post.query.with_parent(account).filter(Post.id != oldest_post.id).order_by(db.func.random()).limit(99).all()
posts.append(oldest_post)
posts = refresh_posts(posts)
db.session.commit()
return posts
@app.task
def refresh_account_with_oldest_post():
post = Post.query.options(db.joinedload(Post.author)).order_by(db.asc(Post.updated_at)).first()
return refresh_account(post.author_id)
app.add_periodic_task(6*60*60, periodic_cleanup) app.add_periodic_task(6*60*60, periodic_cleanup)
app.add_periodic_task(45, queue_fetch_for_most_stale_accounts) app.add_periodic_task(45, queue_fetch_for_most_stale_accounts)
app.add_periodic_task(45, queue_deletes) app.add_periodic_task(45, queue_deletes)
app.add_periodic_task(30*60, refresh_account_with_oldest_post)
if __name__ == '__main__': if __name__ == '__main__':
app.worker_main() app.worker_main()

View File

@ -21,7 +21,7 @@
{% endif %} {% endif %}
</div> </div>
{% set post_count = g.viewer.account.post_count() %} {% set post_count = g.viewer.account.post_count() %}
<p>Currently keeping track of {{ post_count }} posts</p> <p>Currently keeping track of {{ post_count }} of your posts, roughly {{ g.viewer.account.estimate_eligible_for_delete() }} of which currently match your expiration rules.</p>
{% if g.viewer.account.service == 'twitter' {% if g.viewer.account.service == 'twitter'
and post_count < g.viewer.account.reported_post_count * 3/4 and post_count < g.viewer.account.reported_post_count * 3/4
and g.viewer.account.reported_post_count > 3200 -%} and g.viewer.account.reported_post_count > 3200 -%}
@ -37,21 +37,21 @@
{% endif %} {% endif %}
<form action='{{url_for("settings")}}' method='post' enctype='multipart/form-data'> <form action='{{url_for("settings")}}' method='post' enctype='multipart/form-data'>
<p>Delete one post every <p>Posts that are less than
{{interval_input(g.viewer.account, 'policy_delete_every', scales)}}
</p>
<p>Keep posts less than
{{interval_input(g.viewer.account, 'policy_keep_younger', scales)}} {{interval_input(g.viewer.account, 'policy_keep_younger', scales)}}
old old are considered fresh
</p> </p>
<p>Keep my <p>Your latest
<input type=number name=policy_keep_latest min=0 step=1 style='max-width:8ch' value={{g.viewer.account.policy_keep_latest}}> <input type=number name=policy_keep_latest min=0 step=1 style='max-width:8ch' value={{g.viewer.account.policy_keep_latest}}>
latest posts posts are considered fresh
</p> </p>
<p>Keep posts that I have favourited <p>Posts that you have given a like to stay fresh forever
<label><input type=radio name=policy_keep_favourites value=true {{ "checked" if g.viewer.account.policy_keep_favourites }}> Yes</label> <label><input type=radio name=policy_keep_favourites value=true {{ "checked" if g.viewer.account.policy_keep_favourites }}> Yes</label>
<label><input type=radio name=policy_keep_favourites value=false {{ "checked" if not g.viewer.account.policy_keep_favourites }}> No</label> <label><input type=radio name=policy_keep_favourites value=false {{ "checked" if not g.viewer.account.policy_keep_favourites }}> No</label>
</p> </p>
<p>Any post that is not kept fresh by any of these rules is considered expired. One random expired post will be deleted every
{{interval_input(g.viewer.account, 'policy_delete_every', scales)}}
</p>
<input type=submit value='Save settings'> <input type=submit value='Save settings'>
</form> </form>

20
templates/warn.html Normal file
View File

@ -0,0 +1,20 @@
{% extends 'lib/layout.html' %}
{% block body %}
<section>
<h2>Ahhhh (dats me yellin)</h2>
<div class="banner warning">
<p>{{message|safe}}</p>
<div>
<form method='post'>
<input name='confirm' value='Do it' type='submit'/>
</form>
<form action='{{url_for("index")}}'>
<input name='confirm' value='Cancel' type='submit'/>
</form>
</div>
</div>
</section>
{% endblock %}