You've already forked minishortener
92 lines
2.8 KiB
Python
92 lines
2.8 KiB
Python
#!/bin/python3
|
|
|
|
from flask import Flask, render_template, redirect, request
|
|
from flask_httpauth import HTTPBasicAuth
|
|
from werkzeug.security import generate_password_hash, check_password_hash
|
|
from datetime import datetime
|
|
import os, sqlite3, string, random, time
|
|
|
|
template_dir = os.path.abspath('.')
|
|
app = Flask(__name__, template_folder=template_dir)
|
|
auth = HTTPBasicAuth()
|
|
|
|
if not (user := os.getenv('USER')):
|
|
user = 'admin'
|
|
if not (password := os.getenv('PASS')):
|
|
password = 'admin'
|
|
|
|
users = {
|
|
user: generate_password_hash(password)
|
|
}
|
|
|
|
@auth.verify_password
|
|
def verify_password(username, password):
|
|
if username in users:
|
|
return check_password_hash(users.get(username), password)
|
|
return False
|
|
|
|
con = sqlite3.connect('urls.db')
|
|
cur = con.cursor()
|
|
cur.execute('CREATE TABLE IF NOT EXISTS urls (id INTEGER PRIMARY KEY, url TEXT, short TEXT, clicks INTEGER, date TEXT)')
|
|
con.commit()
|
|
|
|
@app.route('/admin', methods=['GET'])
|
|
@auth.login_required
|
|
def admin():
|
|
host = request.host_url
|
|
cur.execute('SELECT * FROM urls ORDER BY clicks DESC')
|
|
data = cur.fetchall()
|
|
return render_template('index.html', data=data, host=host, admin=True)
|
|
|
|
@app.route('/delete/<id>', methods=['GET'])
|
|
@auth.login_required
|
|
def delete(id):
|
|
cur.execute('DELETE FROM urls WHERE id = ?', (id,))
|
|
con.commit()
|
|
return redirect('/admin')
|
|
|
|
@app.route('/stats/<short>', methods=['GET'])
|
|
def stats(short):
|
|
host = request.host_url
|
|
cur.execute('SELECT * FROM urls WHERE short = ?', (short,))
|
|
data = cur.fetchall()
|
|
return render_template('index.html', data=data, host=host)
|
|
|
|
@app.route('/shorten', methods=['POST'])
|
|
def shorten():
|
|
host = request.host_url
|
|
url = request.form['url']
|
|
if url == '':
|
|
return redirect('/')
|
|
elif url == 'admin':
|
|
return redirect('/admin')
|
|
elif url.startswith(host) and url.split('/')[-1]:
|
|
return redirect('/stats/' + url.split('/')[-1])
|
|
elif not url.startswith('http'):
|
|
url = 'http://' + url
|
|
short = ''.join(random.choices(string.ascii_letters + string.digits, k=7))
|
|
cur.execute('INSERT INTO urls (url, short, clicks, date) VALUES (?, ?, ?, ?)', (url, short, 0, datetime.now()))
|
|
con.commit()
|
|
return render_template('index.html', short=short, host=host)
|
|
|
|
@app.route('/<short>')
|
|
def geturl(short):
|
|
cur.execute('SELECT url FROM urls WHERE short=?', (short,))
|
|
try:
|
|
url = cur.fetchone()[0]
|
|
except:
|
|
return render_template('index.html', error='Invalid short URL')
|
|
cur.execute('UPDATE urls SET clicks=clicks+1 WHERE short=?', (short,))
|
|
con.commit()
|
|
if not url.startswith('http'):
|
|
url = 'http://' + url
|
|
return redirect(url)
|
|
|
|
@app.route('/', methods=['GET'])
|
|
def self():
|
|
host = request.host_url
|
|
return render_template('index.html', host=host)
|
|
|
|
@app.route('/favicon.ico')
|
|
def favicon():
|
|
return ("Not found"), 404 |