from datetime import datetime, timedelta
from secrets import token_urlsafe
from flask import render_template, flash, redirect, url_for, abort, request, Markup
from app import app, db
from app.forms import UrlForm
from app.models import Url
from app.database_cleaner import check_url
domain = 'http://127.0.0.1:5000'
@app.before_request
def before_request():
pass
@app.route('/index', methods=['GET', 'POST'])
def index():
form = UrlForm()
if form.validate_on_submit():
hash = getHash()
if hash is None:
return redirect(url_for('index'))
death = calcDeath(form.retention.data, int(form.retention_type.data))
view_counter = None if form.retention_type.data != 4 else form.retention.data
if death is None and view_counter is None:
app.logger.warning("Neither death nor view_counter was recieved for url")
flash('Please specify a retention time')
return redirect(url_for('index'))
url = Url(url = form.url.data.strip(), hash=hash, death=death, view_counter=view_counter)
db.session.add(url)
db.session.commit()
death = None if url.death is None else url.death.strftime('%Y-%m-%d %H:%M:%S')
app.logger.info(f"{getClientIp()} created hash '{url.hash}' for '{url.url}'. Death: {death}, View Counter: {url.view_counter}")
link = url_for("resolve_hash", hash=hash, _external = True)
flash(Markup(f'Your url is shortend to {link}'))
return redirect(url_for('index'))
return render_template("index.html", form=form)
def getHash():
for i in range(200):
hash = token_urlsafe(3)
url = Url.query.filter_by(hash=hash).first()
if (url is None and url != 'index'):
return hash
flash('Failed generating a unique hash. Please try again.')
return None
def getClientIp():
if app.config['REVERSE_PROXY'] == 0:
return request.remote_addr
if app.config['REVERSE_PROXY'] == 1:
return request.environ['HTTP_X_FORWARDED_FOR']
def calcDeath(retention, retention_type):
if retention_type == 1:
return datetime.now() + timedelta(minutes=retention)
if retention_type == 2:
return datetime.now() + timedelta(hours=retention)
if retention_type == 3:
return datetime.now() + timedelta(days=retention)
if retention_type == 4:
return None
app.logger.error(f"Retention_type out of range: '{retention_type}'")
@app.route('/', defaults={'hash' : 'index'})
@app.route('/')
def resolve_hash(hash):
if hash == 'index':
return redirect(url_for('index'))
url = Url.query.filter_by(hash=hash).first_or_404()
if check_url(url) is not None: abort(404)
if url.view_counter is not None:
url.view_counter -= 1
db.session.commit()
countermessage = "" if url.view_counter is None else f". View counter was lowered to {url.view_counter}"
app.logger.info(f"{getClientIp()} requested hash '{url.hash}' which resolved to '{url.url}'{countermessage}")
return redirect(url.url, 301)