allow positioning of files

pull/134/head
Aevann 2023-02-26 14:08:37 +02:00
parent 490d5765fa
commit 6ac9b32834
19 changed files with 65 additions and 101 deletions

View File

@ -265,64 +265,35 @@ document.onpaste = function(event) {
const focused = document.activeElement;
const files = structuredClone(event.clipboardData.files);
if (files.length > 4)
{
alert("You can't upload more than 4 files at one time!")
return
}
if (!files.length) return
if (focused.id.includes('reply-form-body-')) {
const fullname = focused.dataset.fullname;
f=document.getElementById('file-upload-reply-' + fullname);
try {
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename-show-reply-' + fullname).textContent = filename;
}
catch(e) {}
f.files = files;
changename('filename-show-reply-' + fullname, f.id, focused.id)
}
else if (focused.id.includes('comment-edit-body-')) {
const id = focused.dataset.id;
f=document.getElementById('file-edit-reply-' + id);
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename-edit-reply-' + id).textContent = filename;
changename('filename-edit-reply-' + id, f.id, focused.id)
}
else if (focused.id.includes('post-edit-box-')) {
const id = focused.dataset.id;
f=document.getElementById('file-upload-edit-' + id);
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename-show-edit-' + id).textContent = filename;
changename('filename-show-edit-' + id, f.id, focused.id)
}
else if (focused.id == "input-message") {
f=document.getElementById('file-upload');
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename').textContent = filename;
changename('filename', f.id, focused.id)
}
else if (focused.id == "input-message-mobile") {
f=document.getElementById('file-upload-mobile');
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename-mobile').textContent = filename;
changename('filename-mobile', f.id, focused.id)
}
}

View File

@ -1,19 +1,9 @@
document.onpaste = function(event) {
const files = structuredClone(event.clipboardData.files);
if (files.length > 4)
{
alert("You can't upload more than 4 files at one time!")
return
}
if (!files.length) return
const f = document.getElementById('file-upload');
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename').textContent = filename;
changename('filename', f.id, 'input-message')
}

View File

@ -244,7 +244,8 @@ function escapeHTML(unsafe) {
return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function changename(s1,s2) {
function changename(s1,s2,textarea) {
console.log('nigg')
const files = document.getElementById(s2).files;
if (files.length > 4)
{
@ -252,11 +253,24 @@ function changename(s1,s2) {
document.getElementById(s2).value = null
return
}
const ta = document.getElementById(textarea);
ta.value = ta.value.replace(/<file>\n/g, "")
if (ta.value) {
ta.value += '\n'
}
let filename = '';
for (const e of files) {
filename += e.name.substr(0, 22) + ', ';
ta.value += '<file>\n'
}
document.getElementById(s1).innerHTML = escapeHTML(filename.slice(0, -2));
console.log(ta)
autoExpand(ta)
ta.focus()
ta.selectionStart = ta.selectionEnd = ta.value.length;
}
function showmore(t) {

View File

@ -101,24 +101,14 @@ function updatebgselection(){
document.onpaste = function(event) {
const focused = document.activeElement;
if (focused.id == 'bio-text') {
if (focused.id == 'profile-bio-text') {
const files = structuredClone(event.clipboardData.files);
if (files.length > 4)
{
alert("You can't upload more than 4 files at one time!")
return
}
if (files.length)
{
f=document.getElementById('file-upload');
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
f.files = files;
document.getElementById('filename-show').textContent = filename;
changename('filename-show', f.id, focused.id)
}
}
}

View File

@ -78,12 +78,8 @@ document.onpaste = function(event) {
{
filename = filename.name.toLowerCase()
if (document.activeElement.id == 'post-text') {
let filename = ''
for (const file of files)
filename += file.name + ', '
filename = filename.toLowerCase().slice(0, -2)
document.getElementById('file-upload-submit').value = files;
document.getElementById('filename-show-submit').textContent = filename;
changename('filename-show-submit', 'file-upload-submit', 'post-text')
}
else {
f=document.getElementById('file-upload');

View File

@ -25,8 +25,7 @@ def media_ratelimit(v):
count = g.db.query(Media).filter(Media.user_id == v.id, Media.created_utc > t).count()
if count > 50: abort(500)
def process_files(files, v):
body = ''
def process_files(files, v, body):
if g.is_tor or not files.get("file"): return body
files = files.getlist('file')[:4]
@ -34,15 +33,17 @@ def process_files(files, v):
media_ratelimit(v)
for file in files:
if '<file>' not in body:
abort(400, "Missing <file> in text!")
if file.content_type.startswith('image/'):
name = f'/images/{time.time()}'.replace('.','') + '.webp'
file.save(name)
url = process_image(name, v)
body += f"\n\n![]({url})"
body = body.replace('<file>', f"![]({url})", 1)
elif file.content_type.startswith('video/'):
body += f"\n\n{SITE_FULL}{process_video(file, v)}"
body = body.replace('<file>', f"{SITE_FULL}{process_video(file, v)}", 1)
elif file.content_type.startswith('audio/'):
body += f"\n\n{SITE_FULL}{process_audio(file, v)}"
body = body.replace('<file>', f"{SITE_FULL}{process_audio(file, v)}", 1)
else:
abort(415)
return body
@ -229,13 +230,15 @@ def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[in
return filename
def process_dm_images(v, user):
def process_dm_images(v, user, body):
if not request.files.get("file") or g.is_tor or not get_setting("dm_images"):
return ''
body = ''
files = request.files.getlist('file')[:4]
for file in files:
if '<file>' not in body:
abort(400, "Missing <file> in text!")
if file.content_type.startswith('image/'):
filename = f'/dm_images/{time.time()}'.replace('.','') + '.webp'
file.save(filename)
@ -263,12 +266,12 @@ def process_dm_images(v, user):
try: url = req['files'][0]['url']
except: abort(400, req['description'])
body += f'\n\n{url}\n\n'
body = body.replace('<file>', url, 1)
with open(f"{LOG_DIRECTORY}/dm_images.log", "a+", encoding="utf-8") as f:
if user:
f.write(f'{url}, {v.username}, {v.id}, {user.username}, {user.id}, {int(time.time())}\n')
else:
f.write(f'{url}, {v.username}, {v.id}, Modmail, Modmail, {int(time.time())}\n')
if body:
with open(f"{LOG_DIRECTORY}/dm_images.log", "a+", encoding="utf-8") as f:
if user:
f.write(f'{body.strip()}, {v.username}, {v.id}, {user.username}, {user.id}, {int(time.time())}\n')
else:
f.write(f'{body.strip()}, {v.username}, {v.id}, Modmail, Modmail, {int(time.time())}\n')
return body
return body.strip()

View File

@ -159,6 +159,8 @@ def comment(v:User):
media_ratelimit(v)
for file in files:
if '<file>' not in body: abort(400, "Missing <file> in text!")
if file.content_type.startswith('image/'):
oldname = f'/images/{time.time()}'.replace('.','') + '.webp'
file.save(oldname)
@ -201,11 +203,11 @@ def comment(v:User):
purge_files_in_cache(f"https://{SITE}/assets/images/badges/{badge.id}.webp")
except Exception as e:
abort(400, str(e))
body += f"\n\n![]({image})"
body = body.replace('<file>', f"![]({image})", 1)
elif file.content_type.startswith('video/'):
body += f"\n\n{SITE_FULL}{process_video(file, v)}"
body = body.replace('<file>', f"{SITE_FULL}{process_video(file, v)}", 1)
elif file.content_type.startswith('audio/'):
body += f"\n\n{SITE_FULL}{process_audio(file, v)}"
body = body.replace('<file>', f"{SITE_FULL}{process_audio(file, v)}", 1)
else:
abort(415)
@ -405,7 +407,7 @@ def edit_comment(cid, v):
execute_antispam_comment_check(body, v)
body += process_files(request.files, v)
body = process_files(request.files, v, body)
body = body.strip()[:COMMENT_BODY_LENGTH_LIMIT] # process_files potentially adds characters to the post
body_for_sanitize = body

View File

@ -294,7 +294,7 @@ def edit_post(pid, v):
p.title = title
p.title_html = title_html
body += process_files(request.files, v)
body = process_files(request.files, v, body)
body = body.strip()[:POST_BODY_LENGTH_LIMIT] # process_files() may be adding stuff to the body
if body != p.body:
@ -655,7 +655,7 @@ def submit_post(v:User, sub=None):
body, bets, options, choices = sanitize_poll_options(v, body, True)
body += process_files(request.files, v)
body = process_files(request.files, v, body)
body = body.strip()[:POST_BODY_LENGTH_LIMIT] # process_files() adds content to the body, so we need to re-strip
torture = (v.agendaposter and not v.marseyawarded and sub != 'chudrama')

View File

@ -298,7 +298,7 @@ def settings_personal_post(v):
elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and \
(request.values.get("bio") or request.files.get('file')):
bio = request.values.get("bio")[:1500]
bio += process_files(request.files, v)
bio = process_files(request.files, v, bio)
bio = bio.strip()
bio_html = sanitize(bio, blackjack="bio")

View File

@ -256,7 +256,7 @@ def submit_contact(v):
abort(403)
body = f'This message has been sent automatically to all admins via [/contact](/contact)\n\nMessage:\n\n{body}'
body += process_files(request.files, v)
body = process_files(request.files, v, body)
body = body.strip()
body_html = sanitize(body)

View File

@ -518,7 +518,7 @@ def message2(v:User, username:str):
message = sanitize_raw_body(request.values.get("message"), False)
message += process_dm_images(v, user)
message = process_dm_images(v, user, message)
if not message: abort(400, "Message is empty!")
@ -592,9 +592,7 @@ def messagereply(v:User):
and hasattr(user, 'is_blocked') and user.is_blocked):
abort(403, f"You're blocked by @{user.username}")
body += process_dm_images(v, user)
body = body.strip()
body = process_dm_images(v, user, body)
if not body: abort(400, "Message is empty!")

View File

@ -116,7 +116,7 @@
<span class="my-auto ml-1">
<label class="btn btn-secondary format mb-0">
<div id="filename" class="mr-3" style="font-size:12px"><i class="fas fa-image" style="font-size:1.3rem!important"></i></div>
<input autocomplete="off" id="file" accept="image/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file')" hidden>
<input autocomplete="off" id="file" accept="image/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file','input-text')" hidden>
</label>
</span>

View File

@ -273,7 +273,7 @@
<label class="btn btn-secondary format m-0" for="file-edit-reply-{{c.id}}">
<div id="filename-edit-reply-{{c.id}}"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-edit-reply-{{c.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-edit-reply-{{c.id}}','file-edit-reply-{{c.id}}')" hidden>
<input autocomplete="off" id="file-edit-reply-{{c.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-edit-reply-{{c.id}}','file-edit-reply-{{c.id}}','comment-edit-body-{{c.id}}')" hidden>
</label>
</div>
<a class="text-small mt-3 d-inline-block" href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a>
@ -540,7 +540,7 @@
<label class="btn btn-secondary m-0 mt-3 {% if upload_disabled %}disabled{% endif %}" for="file-upload-reply-{{c.fullname}}">
<div id="filename-show-reply-{{c.fullname}}"><i class="fas fa-image"></i></div>
<input autocomplete="off" id="file-upload-reply-{{c.fullname}}" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-reply-{{c.fullname}}','file-upload-reply-{{c.fullname}}')" hidden>
<input autocomplete="off" id="file-upload-reply-{{c.fullname}}" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-reply-{{c.fullname}}','file-upload-reply-{{c.fullname}}','reply-form-body-{{c.id}}')" hidden>
</label>
</div>

View File

@ -16,7 +16,7 @@
</label>
<label class="btn btn-secondary m-0 mt-3" for="file-upload">
<div id="filename"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload" accept="image/*, video/*, audio/*" type="file" name="file" multiple="multiple" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file-upload')" hidden>
<input autocomplete="off" id="file-upload" accept="image/*, video/*, audio/*" type="file" name="file" multiple="multiple" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file-upload','input-message')" hidden>
</label>
<input type="submit" data-nonce="{{g.nonce}}" data-onclick="disable(this)" value="Submit" class="btn btn-primary mt-3">
</form>

View File

@ -88,7 +88,7 @@
{% if show_file_upload %}
<label style="padding:0.3rem" class="btn btn-secondary format d-inline-block m-0">
<div id="filename-show"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload" accept="image/*, video/*, audio/*" type="file" name="file" multiple="multiple" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show','file-upload')" hidden>
<input autocomplete="off" id="file-upload" accept="image/*, video/*, audio/*" type="file" name="file" multiple="multiple" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show','file-upload','{{id}}-text')" hidden>
</label>
{% endif %}
</div>

View File

@ -178,7 +178,7 @@
<label class="format btn btn-secondary m-0 {% if v %}d-inline-block{% else %}d-none{% endif %}" for="file-upload-edit-{{p.id}}">
<div id="filename-show-edit-{{p.id}}"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload-edit-{{p.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-edit-{{p.id}}','file-upload-edit-{{p.id}}')" hidden>
<input autocomplete="off" id="file-upload-edit-{{p.id}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-edit-{{p.id}}','file-upload-edit-{{p.id}}','post-edit-box-{{p.id}}')" hidden>
</label>
<small class="format d-none"><i class="fas fa-link"></i></small>

View File

@ -62,7 +62,7 @@
<button type="button" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('post-text')" class="btn btn-secondary format d-inline-block m-0" id="emoji-reply-btn" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add Emoji"><i class="fas fa-smile-beam"></i></button>
<label class="format btn btn-secondary m-0 ml-2 {% if v %}d-inline-block{% else %}d-none{% endif %}" for="file-upload-submit">
<div id="filename-show-submit"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload-submit" multiple="multiple" accept="image/*, video/*, audio/*" type="file" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-submit','file-upload-submit');checkForRequired()" hidden>
<input autocomplete="off" id="file-upload-submit" multiple="multiple" accept="image/*, video/*, audio/*" type="file" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-submit','file-upload-submit','post-text');checkForRequired()" hidden>
</label>
<div id="preview" class="preview my-3"></div>
<div class="form-text text-small mt-1 mb-3"><a href="/formatting" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>Formatting help</a></div>

View File

@ -161,7 +161,7 @@
<label class="btn btn-secondary m-0 py-1 px-2 {% if upload_disabled %}disabled{% endif %}" for="file-upload">
<div id="filename"><i class="fas fa-image"></i></div>
<input autocomplete="off" id="file-upload" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file-upload')" hidden>
<input autocomplete="off" id="file-upload" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename','file-upload','input-message')" hidden>
</label>
&nbsp;
@ -468,7 +468,7 @@
<label class="btn btn-secondary m-0 py-1 px-2 {% if upload_disabled %}disabled{% endif %}" for="file-upload-mobile">
<div id="filename-mobile"><i class="fas fa-image"></i></div>
<input autocomplete="off" id="file-upload-mobile" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-mobile','file-upload-mobile')" hidden>
<input autocomplete="off" id="file-upload-mobile" accept="image/*" type="file" name="file" multiple="multiple" {% if upload_disabled %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-mobile','file-upload-mobile','input-message')" hidden>
</label>
&nbsp;

View File

@ -130,7 +130,7 @@
{% if allow_file_upload %}
<label class="format btn btn-secondary m-0 {% if v %}d-inline-block{% else %}d-none{% endif %}" for="file-upload-reply-{{target_fullname}}">
<div id="filename-show-reply-{{target_fullname}}"><i class="fas fa-file"></i></div>
<input autocomplete="off" id="file-upload-reply-{{target_fullname}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-reply-{{target_fullname}}','file-upload-reply-{{target_fullname}}')" hidden>
<input autocomplete="off" id="file-upload-reply-{{target_fullname}}" accept="image/*, video/*, audio/*" type="file" multiple="multiple" name="file" {% if g.is_tor %}disabled{% endif %} data-nonce="{{g.nonce}}" data-onchange="changename('filename-show-reply-{{target_fullname}}','file-upload-reply-{{target_fullname}}','reply-form-body-{{target_fullname}}')" hidden>
</label>
{% endif %}
</div>