Import
This commit is contained in:
commit
3ab71ad847
82
app.py
Normal file
82
app.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import redis, os, random, string, re
|
||||||
|
from datetime import timedelta
|
||||||
|
from flask import Flask, request, render_template, send_from_directory
|
||||||
|
from werkzeug.utils import secure_filename
|
||||||
|
r = redis.Redis('localhost')
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
DEFAULT_TTL = 86400
|
||||||
|
MAX_TTL = 259200
|
||||||
|
UPLOAD_DIR = '/storage/'
|
||||||
|
UPLOAD_SIZE = 200 * 1024 * 1024
|
||||||
|
|
||||||
|
def tdelta(input):
|
||||||
|
keys = ["weeks", "days", "hours", "minutes", "seconds"]
|
||||||
|
regex = "".join(["((?P<%s>\d+)%s ?)?" % (k, k[0]) for k in keys])
|
||||||
|
kwargs = {}
|
||||||
|
for k,v in re.match(regex, input).groupdict(default="0").items():
|
||||||
|
kwargs[k] = int(v)
|
||||||
|
return int(timedelta(**kwargs).total_seconds())
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def index():
|
||||||
|
return render_template('index.html')
|
||||||
|
|
||||||
|
@app.route('/', defaults={'ttl': 3600, 'filename': None, 'isttl': False, 'isfilename': False}, methods=['PUT'])
|
||||||
|
@app.route('/<filename>', defaults={'ttl': None, 'isttl': False, 'isfilename': True}, methods=['PUT'])
|
||||||
|
@app.route('/<ttl>/<filename>', defaults={'isttl': True, 'isfilename': True}, methods=['PUT'])
|
||||||
|
def upload(ttl, filename, isttl, isfilename):
|
||||||
|
if isttl and ttl.isdigit():
|
||||||
|
if int(ttl) > MAX_TTL or int(ttl) < 1:
|
||||||
|
ttl = MAX_TTL
|
||||||
|
else:
|
||||||
|
ttl = int(ttl)
|
||||||
|
elif isttl and not ttl.isdigit():
|
||||||
|
if tdelta(ttl) > MAX_TTL or tdelta(ttl) < 1:
|
||||||
|
ttl = DEFAULT_TTL
|
||||||
|
else:
|
||||||
|
ttl = tdelta(ttl)
|
||||||
|
if isfilename:
|
||||||
|
filename = secure_filename(filename)
|
||||||
|
else:
|
||||||
|
filename = 'file.dat'
|
||||||
|
if len(request.data) > UPLOAD_SIZE:
|
||||||
|
return 'File too large', 422
|
||||||
|
else:
|
||||||
|
key = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(6))
|
||||||
|
r.set(key, filename, ttl)
|
||||||
|
with open(UPLOAD_DIR + key, 'wb') as f:
|
||||||
|
f.write(request.data)
|
||||||
|
return 'https://files.re/' + key + '/' + filename + '\n'
|
||||||
|
|
||||||
|
@app.route('/<file>', defaults={'filename': None}, methods=['GET'])
|
||||||
|
@app.route('/<file>/<filename>', methods=['GET'])
|
||||||
|
def download(file, filename):
|
||||||
|
if filename == None:
|
||||||
|
filename = r.get(file)
|
||||||
|
else:
|
||||||
|
filename = secure_filename(filename)
|
||||||
|
if r.get(file) is not None:
|
||||||
|
file = secure_filename(file)
|
||||||
|
return send_from_directory(directory=UPLOAD_DIR, filename=file, as_attachment=True, attachment_filename=filename)
|
||||||
|
else:
|
||||||
|
return 'Not found', 404
|
||||||
|
|
||||||
|
@app.route('/view/<file>', methods=['GET'])
|
||||||
|
def view(file):
|
||||||
|
if r.get(file) is not None:
|
||||||
|
file = secure_filename(file)
|
||||||
|
return send_from_directory(directory=UPLOAD_DIR, filename=file, mimetype="text/plain")
|
||||||
|
else:
|
||||||
|
return 'Not found', 404
|
||||||
|
|
||||||
|
@app.route('/ttl/<file>', methods=['GET'])
|
||||||
|
def ttl(file):
|
||||||
|
ttl = r.ttl(file);
|
||||||
|
if ttl is not None:
|
||||||
|
return str(ttl)
|
||||||
|
else:
|
||||||
|
return 'Not found', 404
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
11
listener.py
Normal file
11
listener.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import redis, os
|
||||||
|
|
||||||
|
UPLOAD_DIR = '/storage/'
|
||||||
|
|
||||||
|
r = redis.StrictRedis()
|
||||||
|
pubsub = r.pubsub()
|
||||||
|
pubsub.psubscribe("*")
|
||||||
|
for msg in pubsub.listen():
|
||||||
|
if msg['channel'].decode('utf-8') == '__keyevent@0__:expired':
|
||||||
|
os.remove(UPLOAD_DIR + msg['data'].decode('utf-8'))
|
||||||
|
print("Deleted file " + msg['data'].decode('utf-8'))
|
1
static/min.css
Normal file
1
static/min.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
/* Copyright 2014 Owen Versteeg; MIT licensed */body,textarea,input,select{background:0;border-radius:0;font:16px sans-serif;margin:0}.smooth{transition:all .2s}.btn,.nav a{text-decoration:none}.container{margin:0 20px;width:auto}label>*{display:inline}form>*{display:block;margin-bottom:10px}.btn{background:#999;border-radius:6px;border:0;color:#fff;cursor:pointer;display:inline-block;margin:2px 0;padding:12px 30px 14px}.btn:hover{background:#888}.btn:active,.btn:focus{background:#777}.btn-a{background:#0ae}.btn-a:hover{background:#09d}.btn-a:active,.btn-a:focus{background:#08b}.btn-b{background:#3c5}.btn-b:hover{background:#2b4}.btn-b:active,.btn-b:focus{background:#2a4}.btn-c{background:#d33}.btn-c:hover{background:#c22}.btn-c:active,.btn-c:focus{background:#b22}.btn-sm{border-radius:4px;padding:10px 14px 11px}.row{margin:1% 0;overflow:auto}.col{float:left}.table,.c12{width:100%}.c11{width:91.66%}.c10{width:83.33%}.c9{width:75%}.c8{width:66.66%}.c7{width:58.33%}.c6{width:50%}.c5{width:41.66%}.c4{width:33.33%}.c3{width:25%}.c2{width:16.66%}.c1{width:8.33%}h1{font-size:3em}.btn,h2{font-size:2em}.ico{font:33px Arial Unicode MS,Lucida Sans Unicode}.addon,.btn-sm,.nav,textarea,input,select{outline:0;font-size:14px}textarea,input,select{padding:8px;border:1px solid #ccc}textarea:focus,input:focus,select:focus{border-color:#5ab}textarea,input[type=text]{-webkit-appearance:none;width:13em}.addon{padding:8px 12px;box-shadow:0 0 0 1px #ccc}.nav,.nav .current,.nav a:hover{background:#000;color:#fff}.nav{height:24px;padding:11px 0 15px}.nav a{color:#aaa;padding-right:1em;position:relative;top:-1px}.nav .pagename{font-size:22px;top:1px}.btn.btn-close{background:#000;float:right;font-size:25px;margin:-54px 7px;display:none}@media(min-width:1310px){.container{margin:auto;width:1270px}}@media(max-width:870px){.row .col{width:100%}}@media(max-width:500px){.btn.btn-close{display:block}.nav{overflow:hidden}.pagename{margin-top:-11px}.nav:active,.nav:focus{height:auto}.nav div:before{background:#000;border-bottom:10px double;border-top:3px solid;content:'';float:right;height:4px;position:relative;right:3px;top:14px;width:20px}.nav a{padding:.5em 0;display:block;width:50%}}.table th,.table td{padding:.5em;text-align:left}.table tbody>:nth-child(2n-1){background:#ddd}.msg{padding:1.5em;background:#def;border-left:5px solid #59d}
|
71
templates/index.html
Normal file
71
templates/index.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>t.lsd.cat ~ Temp file storage</title>
|
||||||
|
<style>
|
||||||
|
pre {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 0 1.625em;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
overflow-x: auto;
|
||||||
|
display: block;
|
||||||
|
padding: 0 1em;
|
||||||
|
background: #657b83;
|
||||||
|
background-image: -webkit-linear-gradient(#5e737a 50%, transparent 50%);
|
||||||
|
background-image: linear-gradient(#5e737a 50%, transparent 50%);
|
||||||
|
background-size: 100% 3em;
|
||||||
|
background-position: 0 1.5em;
|
||||||
|
background-origin: content-box;
|
||||||
|
color: #fdf6e3;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
max-width: 70em;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2em 4em;
|
||||||
|
background: #EEE8D5;
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2 {
|
||||||
|
color: #657b83;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>t.lsd.cat</h1>
|
||||||
|
<p><small><i>MAX SIZE 500MB</i> ~ <i>MAX TLL 3 days</i></small></p>
|
||||||
|
<hr>
|
||||||
|
<h2>Usage</h2>
|
||||||
|
<p>Files can be directly uploaded from the command line using:<p>
|
||||||
|
<pre><code>
|
||||||
|
curl --upload-file <localfile> https://t.lsd.cat/
|
||||||
|
</code></pre>
|
||||||
|
<p>The above example will upload a file using the default TTL of 24 hours. For a custom TTL:</p>
|
||||||
|
<pre><code>
|
||||||
|
curl --upload-file <localfile> https://t.lsd.cat/160/ # 160 seconds
|
||||||
|
curl --upload-file <localfile> https://t.lsd.cat/2d3h5s/ # 2 days, 3 hours and 2 seconds
|
||||||
|
</code></pre>
|
||||||
|
<p>It is also possible to know the remaining TLL of an uploaded file:</p>
|
||||||
|
<pre><code>
|
||||||
|
curl https://t.lsd.cat/ttl/<id>
|
||||||
|
</code></pre>
|
||||||
|
<p>Files can also be renamed depending on the download request:</p>
|
||||||
|
<pre><code>
|
||||||
|
curl -O https://t.lsd.cat/<id> # Download with original filename
|
||||||
|
curl -O https://t.lsd.cat/<id>/<filename> # Download with <filename>
|
||||||
|
</code></pre>
|
||||||
|
<hr>
|
||||||
|
<footer>
|
||||||
|
<address><a href="https://lsd.cat" target="_blank">https://lsd.cat</a> ~ <a href="https://git.lsd.cat/g/lsd-transfer" target="_blank">Source</a></address>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user