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)