2017-07-27 01:17:28 +02:00
from flask import render_template , url_for , redirect , request , g , Response
2017-08-03 21:37:00 +02:00
from datetime import datetime , timedelta
2017-07-27 00:35:53 +02:00
import lib . twitter
2017-08-01 20:57:15 +02:00
import lib
2017-07-31 04:51:11 +02:00
from lib import require_auth
2017-08-09 14:28:30 +02:00
from lib import set_session_cookie
2017-08-10 17:07:39 +02:00
from lib import get_viewer_session
2017-07-31 00:07:34 +02:00
from model import Account , Session , Post , TwitterArchive
2017-08-10 17:07:39 +02:00
from app import app , db , sentry , limiter
2017-07-30 13:53:14 +02:00
import tasks
2017-08-07 15:35:15 +02:00
from zipfile import BadZipFile
2017-08-09 11:32:32 +02:00
from twitter import TwitterError
2017-08-09 14:27:39 +02:00
from urllib . error import URLError
2017-08-09 11:43:16 +02:00
import version
2017-08-11 17:57:32 +02:00
import lib . brotli
2017-07-25 09:52:24 +02:00
2017-07-27 01:17:28 +02:00
@app.before_request
def load_viewer ( ) :
2017-08-10 17:07:39 +02:00
g . viewer = get_viewer_session ( )
if g . viewer and sentry :
sentry . user_context ( {
' id ' : g . viewer . account . id ,
' username ' : g . viewer . account . screen_name ,
' service ' : g . viewer . account . service
} )
2017-07-27 01:17:28 +02:00
2017-08-09 11:43:16 +02:00
@app.context_processor
def inject_version ( ) :
return dict ( version = version . version )
2017-07-27 01:17:28 +02:00
@app.after_request
def touch_viewer ( resp ) :
2017-08-10 17:07:39 +02:00
if ' viewer ' in g and g . viewer :
2017-08-09 14:28:30 +02:00
set_session_cookie ( g . viewer , resp , app . config . get ( ' HTTPS ' ) )
2017-07-27 01:17:28 +02:00
g . viewer . touch ( )
db . session . commit ( )
return resp
2017-08-11 19:13:37 +02:00
2017-08-11 19:44:09 +02:00
lib . brotli . brotli ( app )
2017-08-11 17:57:32 +02:00
2017-07-25 09:52:24 +02:00
@app.route ( ' / ' )
2017-07-25 23:05:46 +02:00
def index ( ) :
2017-07-28 00:08:20 +02:00
if g . viewer :
2017-08-07 15:40:31 +02:00
return render_template ( ' logged_in.html ' , scales = lib . interval_scales ,
2017-08-07 16:26:25 +02:00
tweet_archive_failed = ' tweet_archive_failed ' in request . args ,
settings_error = ' settings_error ' in request . args
)
2017-07-28 00:08:20 +02:00
else :
2017-08-08 16:18:39 +02:00
return render_template ( ' index.html ' ,
twitter_login_error = ' twitter_login_error ' in request . args )
2017-07-25 09:52:24 +02:00
2017-07-25 23:05:46 +02:00
@app.route ( ' /login/twitter ' )
2017-08-10 17:07:39 +02:00
@limiter.limit ( ' 3/minute ' )
2017-07-27 00:35:53 +02:00
def twitter_login_step1 ( ) :
2017-08-08 16:18:39 +02:00
try :
return redirect ( lib . twitter . get_login_url (
callback = url_for ( ' twitter_login_step2 ' , _external = True ) ,
* * app . config . get_namespace ( " TWITTER_ " )
) )
except ( TwitterError , URLError ) :
return redirect ( url_for ( ' index ' , twitter_login_error = ' ' , _anchor = ' log_in ' ) )
2017-07-27 00:35:53 +02:00
@app.route ( ' /login/twitter/callback ' )
2017-08-10 17:07:39 +02:00
@limiter.limit ( ' 3/minute ' )
2017-07-27 00:35:53 +02:00
def twitter_login_step2 ( ) :
2017-08-08 16:18:39 +02:00
try :
oauth_token = request . args [ ' oauth_token ' ]
oauth_verifier = request . args [ ' oauth_verifier ' ]
token = lib . twitter . receive_verifier ( oauth_token , oauth_verifier , * * app . config . get_namespace ( " TWITTER_ " ) )
2017-07-30 13:53:14 +02:00
2017-08-08 16:18:39 +02:00
session = Session ( account_id = token . account_id )
db . session . add ( session )
db . session . commit ( )
2017-07-30 13:53:14 +02:00
2017-08-08 16:18:39 +02:00
tasks . fetch_acc . s ( token . account_id ) . apply_async ( routing_key = ' high ' )
2017-07-30 13:53:14 +02:00
2017-08-08 16:18:39 +02:00
resp = Response ( status = 302 , headers = { " location " : url_for ( ' index ' ) } )
2017-08-09 14:28:30 +02:00
set_session_cookie ( session , resp , app . config . get ( ' HTTPS ' ) )
2017-08-08 16:18:39 +02:00
return resp
except ( TwitterError , URLError ) :
return redirect ( url_for ( ' index ' , twitter_login_error = ' ' , _anchor = ' log_in ' ) )
2017-07-25 23:05:46 +02:00
2017-07-31 04:51:11 +02:00
@app.route ( ' /upload_tweet_archive ' , methods = ( ' POST ' , ) )
2017-08-10 17:07:39 +02:00
@limiter.limit ( ' 10/10 minutes ' )
2017-07-31 04:51:11 +02:00
@require_auth
def upload_tweet_archive ( ) :
2017-07-31 00:07:34 +02:00
ta = TwitterArchive ( account = g . viewer . account ,
body = request . files [ ' file ' ] . read ( ) )
db . session . add ( ta )
db . session . commit ( )
2017-08-07 15:35:15 +02:00
try :
tasks . chunk_twitter_archive ( ta . id )
2017-07-31 00:07:34 +02:00
2017-08-07 15:35:15 +02:00
assert ta . chunks > 0
return redirect ( url_for ( ' index ' , _anchor = ' recent_archives ' ) )
except ( BadZipFile , AssertionError ) :
2017-08-07 15:44:21 +02:00
return redirect ( url_for ( ' index ' , tweet_archive_failed = ' ' , _anchor = ' tweet_archive_import ' ) )
2017-07-31 04:51:11 +02:00
2017-08-03 16:05:28 +02:00
@app.route ( ' /settings ' , methods = ( ' POST ' , ) )
2017-07-31 04:51:11 +02:00
@require_auth
def settings ( ) :
2017-08-03 16:05:28 +02:00
for attr in (
' policy_keep_favourites ' ,
' policy_keep_latest ' ,
' policy_delete_every_scale ' ,
2017-08-09 09:14:42 +02:00
' policy_delete_every_significand ' ,
2017-08-03 16:05:28 +02:00
' policy_keep_younger_scale ' ,
2017-08-09 09:14:42 +02:00
' policy_keep_younger_significand ' ,
2017-08-08 15:38:54 +02:00
' policy_keep_media ' ,
2017-08-03 16:05:28 +02:00
) :
2017-08-07 16:26:25 +02:00
try :
if attr in request . form :
setattr ( g . viewer . account , attr , request . form [ attr ] )
except ValueError :
return redirect ( url_for ( ' index ' , settings_error = ' ' ) )
2017-07-31 18:29:09 +02:00
2017-08-03 16:05:28 +02:00
db . session . commit ( )
return redirect ( url_for ( ' index ' , settings_saved = ' ' ) )
@app.route ( ' /disable ' , methods = ( ' POST ' , ) )
@require_auth
def disable ( ) :
g . viewer . account . policy_enabled = False
db . session . commit ( )
2017-07-31 18:29:09 +02:00
2017-08-03 16:05:28 +02:00
return redirect ( url_for ( ' index ' ) )
@app.route ( ' /enable ' , methods = ( ' POST ' , ) )
@require_auth
def enable ( ) :
2017-08-03 21:37:00 +02:00
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 ( )
2017-08-03 16:05:28 +02:00
g . viewer . account . policy_enabled = True
db . session . commit ( )
return redirect ( url_for ( ' index ' ) )
2017-07-31 18:29:09 +02:00
2017-07-25 23:05:46 +02:00
@app.route ( ' /logout ' )
2017-07-31 04:51:11 +02:00
@require_auth
2017-07-25 23:05:46 +02:00
def logout ( ) :
2017-07-27 01:17:28 +02:00
if ( g . viewer ) :
db . session . delete ( g . viewer )
db . session . commit ( )
2017-07-27 14:19:40 +02:00
g . viewer = None
2017-07-25 23:05:46 +02:00
return redirect ( url_for ( ' index ' ) )