working on uploads

master
lza_menace 2 years ago
parent ea6d434575
commit 44d1201de7

@ -27,6 +27,7 @@ DATA_PATH = getenv('DATA_PATH', f'{getcwd()}/data')
SESSION_LENGTH = int(getenv('SESSION_LENGTH', 300))
PERMANENT_SESSION_LIFETIME = timedelta(minutes=SESSION_LENGTH)
MAX_CONTENT_LENGTH = 50 * 1024 * 1024 # 50 MB
ALLOWED_UPLOADS = ['jpg', 'jpeg', 'png', 'svg', 'gif', 'mp4', 'webm']
# Development
TEMPLATES_AUTO_RELOAD = True

@ -1,6 +1,7 @@
from flask_wtf import FlaskForm
from wtforms import StringField, FloatField
from wtforms import StringField, BooleanField
from wtforms.validators import DataRequired, ValidationError
from flask_wtf.file import FileField, FileRequired, FileAllowed
from monero.address import address
from nerochan.models import User
@ -46,3 +47,9 @@ class ConfirmTip(FlaskForm):
tx_id = StringField('TX ID:', validators=[DataRequired()], render_kw={'placeholder': 'TX ID', 'class': 'u-full-width', 'type': 'text'})
tx_key = StringField('TX Key:', validators=[DataRequired()], render_kw={'placeholder': 'TX Key', 'class': 'u-full-width', 'type': 'text'})
class CreateArtwork(FlaskForm):
title = StringField('Title:', validators=[DataRequired()], render_kw={'placeholder': 'Title', 'class': 'u-full-width', 'type': 'text'})
description = StringField('Description:', validators=[], render_kw={'placeholder': 'Description', 'class': 'u-full-width', 'type': 'text'})
nsfw = BooleanField('NSFW:')
content = FileField('Upload:', validators=[FileRequired(), FileAllowed(config.ALLOWED_UPLOADS)])

@ -2,7 +2,7 @@ from os import path
from datetime import datetime
from secrets import token_urlsafe
from PIL import Image, ImageSequence
from PIL import Image, ImageSequence, ImageFilter
import peewee as pw
@ -86,6 +86,7 @@ class Artwork(pw.Model):
last_edit_date = pw.DateTimeField(default=datetime.utcnow)
approved = pw.BooleanField(default=False)
hidden = pw.BooleanField(default=False)
nsfw = pw.BooleanField(default=False)
title = pw.CharField()
description = pw.TextField(null=True)
@ -98,8 +99,6 @@ class Artwork(pw.Model):
_t = f'thumbnail-{self.image}'
i = f'{config.DATA_PATH}/uploads/{self.image}'
t = f'{config.DATA_PATH}/uploads/{_t}'
if path.exists(t):
return True
try:
size = (150,150)
image = Image.open(i)
@ -109,14 +108,21 @@ class Artwork(pw.Model):
for frame in frames:
thumbnail = frame.copy()
thumbnail.thumbnail(size, Image.ANTIALIAS)
if self.nsfw:
thumbnail = thumbnail.filter(ImageFilter.GaussianBlur(radius = 4))
yield thumbnail
_frames = thumbnails(frames)
_image = next(_frames)
_image.info = image.info
_image.save(t, format=image.format, save_all=True, append_images=list(_frames), disposal=2)
else:
image.thumbnail(size, Image.ANTIALIAS)
if self.nsfw:
image = image.filter(ImageFilter.GaussianBlur(radius = 4))
image.save(t, format=image.format)
image.close()
self.thumbnail = _t
self.save()

@ -1,9 +1,11 @@
from pathlib import Path
from secrets import token_urlsafe
from flask import Blueprint, render_template, flash, redirect, url_for, request
from flask_login import login_required, current_user
from werkzeug.utils import secure_filename
from nerochan.forms import ConfirmTip
from nerochan.forms import ConfirmTip, CreateArtwork
from nerochan.decorators import admin_required
from nerochan.models import Artwork, Transaction
from nerochan import config
@ -65,12 +67,16 @@ def manage(id, action):
elif not artwork.hidden:
flash('Cannot delete an artwork unless it is hidden first', 'warning')
return redirect(url_for('artwork.show', id=artwork.id))
base = Path(config.DATA_PATH).joinpath('uploads')
base = Path(config.DATA_PATH, 'uploads')
base.joinpath(artwork.image).unlink(missing_ok=True)
base.joinpath(artwork.thumbnail).unlink(missing_ok=True)
artwork.delete_instance()
flash('Artwork has been deleted from the system.', 'success')
return redirect(url_for('artwork.hidden'))
elif action == 'regenerate_thumbnail':
artwork.generate_thumbnail()
flash(f'Generated new thumbnail for artwork {artwork.id}', 'success')
return redirect(url_for('artwork.show', id=artwork.id))
return redirect(url_for('artwork.pending'))
@ -116,7 +122,37 @@ def show(id):
form=form
)
@bp.route('/new', methods=['GET', 'POST'])
@bp.route('/create', methods=['GET', 'POST'])
@login_required
def create():
return 'upload your artwork'
form = CreateArtwork()
if form.validate_on_submit():
rand = token_urlsafe(12)
f = form.content.data
filename = secure_filename(f'{rand}-{f.filename}')
try:
f.save(Path(config.DATA_PATH, 'uploads', filename))
except Exception as e:
flash(f'There was an issue saving the file: {e}')
return redirect(request.referrer)
artwork = Artwork(
user=current_user,
image=filename,
approved=current_user.is_verified,
nsfw=form.nsfw.data,
title=form.title.data,
description=form.description.data
)
artwork.save()
artwork.generate_thumbnail()
if current_user.is_verified:
return redirect(url_for('artwork.show', id=artwork.id))
else:
flash('Artwork has been posted! Please wait for an admin to review and approve it.', 'success')
return redirect(url_for('main.index'))
return render_template(
'artwork/create.html',
form=form
)

@ -12,6 +12,10 @@ a, a:visited {
margin-left: 2em;
}
.ml-4 {
margin-left: 4em;
}
.mt-4 {
margin-top: 4em;
}

@ -0,0 +1,34 @@
{% extends 'includes/base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="one-half column">
<h1>create</h1>
<p>Upload new artwork for the community. Please limit submissions to Monero-Chan (and Wownero-Chan) content only. Please tag NSFW appropriately.</p>
<form method="post" action="" enctype="multipart/form-data">
{% for f in form %}
{% if f.name == 'csrf_token' %}
{{ f }}
{% else %}
{{ f.label }}
{{ f }}
{% endif %}
{% endfor %}
<ul>
{%- for field, errors in form.errors.items() %}
<li>{{ form[field].label }}: {{ ', '.join(errors) }}</li>
{%- endfor %}
</ul>
<input type="submit" value="Submit" class="button-primary">
</form>
</div>
</div>
</div>
{% endblock %}

@ -10,17 +10,22 @@
posted by <a href="{{ url_for('user.show', handle=artwork.user.handle) }}">{{ artwork.user.handle }}</a> - {{ artwork.upload_date | humanize }}
</h6>
<p class="artworkDescription">{{ artwork.description }}</p>
{% if not artwork.approved %}
<div class="row">
{% if artwork.hidden %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='delete') }}"><button class="button-secondary">Delete</button></a>
{% else %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='reject') }}"><button class="button">Reject</button></a>
{% endif %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='approve') }}"><button class="button-primary">Approve</button></a>
</div>
{% endif %}
<div class="row">
{% if not artwork.approved %}
{% if artwork.hidden %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='delete') }}"><button class="button-secondary">Delete</button></a>
{% else %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='reject') }}"><button class="button">Reject</button></a>
{% endif %}
<a href="{{ url_for('artwork.manage', id=artwork.id, action='approve') }}"><button class="button-primary">Approve</button></a>
{% endif %}
{% if current_user.is_authenticated and current_user.is_admin %}
<span class="ml-4">
<a href="{{ url_for('artwork.manage', id=artwork.id, action='regenerate_thumbnail') }}"><button class="button">Regen Thumbnail</button></a>
</span>
{% endif %}
</div>
</div>
<hr>
<div class="row">

@ -4,6 +4,7 @@
<li class="navbar-item"><a class="navbar-link" href="{{ url_for('main.index') }}">Home</a></li>
<li class="navbar-item"><a class="navbar-link" href="{{ url_for('main.about') }}">About</a></li>
{%- if current_user.is_authenticated %}
<li class="navbar-item"><a class="navbar-link" href="{{ url_for('artwork.create') }}">Upload</a></li>
{%- if current_user.is_admin %}
<li class="navbar-item"><a class="navbar-link" href="{{ url_for('admin.dashboard') }}">Admin</a></li>
{% endif %}

Loading…
Cancel
Save