You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
3.0 KiB
82 lines
3.0 KiB
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 <a href="{link}">{link}</a>')) |
|
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('/<hash>') |
|
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)
|
|
|