comics captcha and view fix

This commit is contained in:
aneuhmanh 2025-03-08 02:01:18 +02:00
parent 3fac6070ca
commit db675ccf36
7 changed files with 122 additions and 104 deletions

24
app.py
View File

@ -160,14 +160,11 @@ def view(content_type, id):
content = Comic.query.get_or_404(id)
comments = Comments.query.filter_by(comic_id=id).order_by(Comments.comment_date.desc()).all()
comic_pages_dir = os.path.join(app.config['UPLOAD_FOLDER']['comics'], content.comic_folder)
comic_pages = ComicPage.query.filter_by(comic_id=id).order_by(ComicPage.page_number).all()
if not os.path.exists(comic_pages_dir):
if not comic_pages:
return render_template('error.html', message="Comic pages not found")
comic_pages = os.listdir(comic_pages_dir)
comic_pages = sorted(comic_pages)
all_comics = Comic.query.order_by(Comic.id).all()
comic_ids = [comic.id for comic in all_comics]
current_index = comic_ids.index(id)
@ -530,28 +527,32 @@ async def comic_edit(comic_id):
if action == 'delete' and (page_id := request.form.get('page')):
page = ComicPage.query.get(page_id)
if page:
os.remove(page.file_path)
os.remove(page.file_path.replace('\\', '/'))
db.session.delete(page)
db.session.commit()
pages = ComicPage.query.filter_by(comic_id=comic.id).order_by(ComicPage.page_number).all()
for i, page in enumerate(pages, start=1):
page.page_number = i
db.session.commit()
elif action == 'update' and (page_id := request.form.get('page')) and 'new_page' in request.files:
new_page = request.files['new_page']
filename = f"{uuid.uuid4().hex}.webp"
file_path = os.path.join(cfp, filename)
file_path = os.path.join(cfp, filename).replace('\\', '/')
webp_image = await convert_to_webp(new_page)
async with aiofiles.open(file_path, 'wb') as f:
await f.write(webp_image.read())
page = ComicPage.query.get(page_id)
if page:
os.remove(page.file_path)
os.remove(page.file_path.replace('\\', '/'))
page.file_path = file_path
db.session.commit()
elif action == 'add' and 'new_page' in request.files:
new_page = request.files['new_page']
filename = f"{uuid.uuid4().hex}.webp"
file_path = os.path.join(cfp, filename)
file_path = os.path.join(cfp, filename).replace('\\', '/')
webp_image = await convert_to_webp(new_page)
async with aiofiles.open(file_path, 'wb') as f:
await f.write(webp_image.read())
@ -562,7 +563,8 @@ async def comic_edit(comic_id):
return redirect(url_for('comic_edit', comic_id=comic.id))
return render_template('comic_edit.html', comic=comic, comic_pages=comic.pages, form=form)
comic_pages = ComicPage.query.filter_by(comic_id=comic.id).order_by(ComicPage.page_number).all()
return render_template('comic_edit.html', comic=comic, comic_pages=comic_pages, form=form)
def update_related_tables(old_username, new_username):
@ -862,4 +864,4 @@ def buy_item(item_id):
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
app.run(debug=False)

View File

@ -29,7 +29,6 @@ from config import Config
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, FileField, BooleanField
from wtforms.validators import DataRequired
from flask_wtf import RecaptchaField
from flask_wtf.file import FileAllowed
db = SQLAlchemy()
@ -220,6 +219,14 @@ class UploadVideoForm(FlaskForm):
submit = SubmitField('Upload')
agree_with_rules = BooleanField('I agree with the publication rules', validators=[DataRequired()])
class UploadComicForm(FlaskForm):
title = StringField('Comic Name', validators=[DataRequired()])
thumbnail = FileField('Thumbnail', validators=[DataRequired()])
tags = StringField('Tags (comma-separated)')
recaptcha = RecaptchaField()
agree_with_rules = BooleanField('I agree with the publication rules', validators=[DataRequired(message="You must agree with the publication rules.")])
submit = SubmitField('Upload')
class EditTagsForm(FlaskForm):
tags = StringField('Tags', validators=[DataRequired(), Length(max=100)], render_kw={"placeholder": "Enter tags"})
submit = SubmitField('Save')

15
static/js/comic_upload.js Normal file
View File

@ -0,0 +1,15 @@
let pageCount = 1;
const maxPages = 64;
function addPage() {
if (pageCount >= maxPages) {
alert(`You can't add more than ${maxPages} pages!`);
return;
}
pageCount++;
const newPage = document.createElement("div");
newPage.classList.add("form-group");
newPage.innerHTML = `<label>Page ${pageCount}:</label><input type="file" name="pages[]" class="file-input" accept="image/*" required>`;
document.getElementById("pages").appendChild(newPage);
}

View File

@ -26,8 +26,8 @@
<ul>
{% for page in comic_pages %}
<li>
<img src="{{ url_for('static', filename=page.file_path) }}" alt="Comic Page {{ loop.index }}">
<h3>Page {{ loop.index }}</h3>
<img src="{{ url_for('static', filename=page.file_path) }}" alt="Comic Page {{ page.page_number }}">
<h3>Page {{ page.page_number }}</h3>
<div class="form-group">
<form method="POST" action="{{ url_for('comic_edit', comic_id=comic.id) }}" class="form-group">
{{ form.hidden_tag() }}

View File

@ -5,30 +5,26 @@
<meta charset="UTF-8">
<title>🫐comic upload - artberry🫐</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/comic_upload.css') }}">
<link rel="icon" href="{{ url_for('static', filename='artberry.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='artberry.ico') }}" type="image/x-icon">
<link href="https://fonts.googleapis.com/css2?family=Comfortaa:wght@400&display=swap" rel="stylesheet">
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<h1>Upload Comic</h1>
<form class="upload-comic-form" method="POST" action="{{ url_for('upload.comic_upload') }}" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="title">Comic Name:</label>
<input type="text" name="title" class="input-field" required>
{{ form.title.label }}
{{ form.title(class="input-field") }}
</div>
<div class="form-group">
<label for="thumbnail">Thumbnail:</label>
<input type="file" name="thumbnail" class="file-input" accept="image/*" required>
{{ form.thumbnail.label }}
{{ form.thumbnail(class="file-input", accept="image/*") }}
</div>
<div class="form-group">
<label for="tags">Tags:</label>
<input type="text" name="tags" class="input-field" placeholder="Enter tags, separated by commas">
{{ form.tags.label }}
{{ form.tags(class="input-field", placeholder="Enter tags, separated by commas") }}
</div>
<div id="pages">
<div class="form-group">
<label>Page 1:</label>
@ -36,24 +32,15 @@
</div>
</div>
<button class="button" type="button" onclick="addPage()">Add Page:</button>
<button type="submit" class="button">Upload Comic:</button>
<div class="form-group">
{{ form.recaptcha }}
</div>
<div class="form-group">
{{ form.agree_with_rules.label }}
{{ form.agree_with_rules }}
</div>
{{ form.submit(class="button") }}
</form>
<script>
let pageCount = 1;
const maxPages = 64;
function addPage() {
if (pageCount >= maxPages) {
alert(`You cant add more than ${maxPages} pages!`);
return;
}
pageCount++;
const newPage = document.createElement("div");
newPage.classList.add("form-group");
newPage.innerHTML = `<label>Page ${pageCount}:</label><input type="file" name="pages[]" class="file-input" accept="image/*" required>`;
document.getElementById("pages").appendChild(newPage);
}
</script>
<script src="{{ url_for('static', filename='js/comic_upload.js') }}"></script>
</body>
</html>
</html>

View File

@ -43,13 +43,13 @@
<div class="comic-pages">
{% if comic_pages %}
{% for page in comic_pages %}
<img src="{{ url_for('static', filename='comics/' + content.comic_folder + '/' + page) }}" alt="Page {{ loop.index }}">
<img src="{{ url_for('static', filename=page.file_path.replace('static/', '').replace('\\', '/')) }}" alt="Page {{ page.page_number }}">
{% endfor %}
{% else %}
<p>No pages available for this comic.</p>
{% endif %}
</div>
{% endif %}
{% endif %}
{% if current_user.is_authenticated and current_user.username == content.username %}
<form method="POST" action="{{ url_for('delete', content_type=content_type, content_id=content.id) }}">

119
upload.py
View File

@ -4,7 +4,7 @@ import aiofiles
from flask import Blueprint, render_template, redirect, url_for, request, current_app
from flask_login import login_required, current_user
from werkzeug.utils import secure_filename
from models import db, Image, Video, Comic, ComicPage, Post, Cookies, UploadForm, UploadVideoForm
from models import db, Image, Video, Comic, ComicPage, Post, Cookies, UploadForm, UploadVideoForm, UploadComicForm
from utils import allowed_file, check_file_content, check_file_size, convert_to_webp, generate_unique_filename
upload_bp = Blueprint('upload', __name__)
@ -102,62 +102,69 @@ async def upload_video():
@upload_bp.route('/comic_upload', methods=['GET', 'POST'])
@login_required
async def comic_upload():
if request.method == 'POST':
ct = request.files['thumbnail']
n = request.form['title']
tags = request.form.get('tags', '')
allowed_image_mime_types = {'image/png', 'image/jpeg', 'image/gif', 'image/webp'}
if db.session.execute(db.select(Comic).filter_by(name=n)).scalar():
return render_template('comic_upload.html')
if ct:
if not (allowed_file(ct.filename, current_app.config['ALLOWED_IMAGE_EXTENSIONS']) and
check_file_content(ct, allowed_image_mime_types)):
return redirect(url_for('upload.comic_upload'))
tf = f"{uuid.uuid4().hex}.webp"
tp = os.path.join(current_app.config['UPLOAD_FOLDER']['comicthumbs'], tf)
webp_thumbnail = await convert_to_webp(ct)
async with aiofiles.open(tp, 'wb') as f:
await f.write(webp_thumbnail.read())
cf = os.path.join(current_app.config['UPLOAD_FOLDER']['comics'], n)
os.makedirs(cf, exist_ok=True)
new_comic = Comic(
comic_folder=n,
comic_thumbnail_file=tf,
username=current_user.username,
name=n,
tags=tags
)
db.session.add(new_comic)
db.session.flush()
async def save_pages():
pages = request.files.getlist('pages[]')
for i, p in enumerate(sorted(pages, key=lambda x: x.filename), start=1):
if p:
if not (allowed_file(p.filename, current_app.config['ALLOWED_IMAGE_EXTENSIONS']) and
check_file_content(p, allowed_image_mime_types)):
return redirect(url_for('upload.comic_upload'))
filename = f"{uuid.uuid4().hex}.webp"
file_path = os.path.join(cf, filename)
webp_page = await convert_to_webp(p)
async with aiofiles.open(file_path, 'wb') as f:
await f.write(webp_page.read())
new_page = ComicPage(comic_id=new_comic.id, page_number=i, file_path=file_path)
db.session.add(new_page)
db.session.commit()
await save_pages()
return redirect(url_for('comics'))
form = UploadComicForm()
return render_template('comic_upload.html')
if request.method == 'POST':
if form.validate_on_submit():
ct = form.thumbnail.data
n = form.title.data
tags = form.tags.data
allowed_image_mime_types = {'image/png', 'image/jpeg', 'image/gif', 'image/webp'}
if db.session.execute(db.select(Comic).filter_by(name=n)).scalar():
return render_template('comic_upload.html', form=form)
if ct:
if not (allowed_file(ct.filename, current_app.config['ALLOWED_IMAGE_EXTENSIONS']) and
check_file_content(ct, allowed_image_mime_types)):
return redirect(url_for('upload.comic_upload'))
tf = f"{uuid.uuid4().hex}.webp"
tp = os.path.join(current_app.config['UPLOAD_FOLDER']['comicthumbs'], tf)
webp_thumbnail = await convert_to_webp(ct)
async with aiofiles.open(tp, 'wb') as f:
await f.write(webp_thumbnail.read())
cf = os.path.join(current_app.config['UPLOAD_FOLDER']['comics'], n)
os.makedirs(cf, exist_ok=True)
new_comic = Comic(
comic_folder=n,
comic_thumbnail_file=tf,
username=current_user.username,
name=n,
tags=tags
)
db.session.add(new_comic)
db.session.flush()
async def save_pages():
pages = request.files.getlist('pages[]')
for i, p in enumerate(sorted(pages, key=lambda x: x.filename), start=1):
if p:
if not (allowed_file(p.filename, current_app.config['ALLOWED_IMAGE_EXTENSIONS']) and
check_file_content(p, allowed_image_mime_types)):
return redirect(url_for('upload.comic_upload'))
filename = f"{uuid.uuid4().hex}.webp"
file_path = os.path.join(cf, filename)
webp_page = await convert_to_webp(p)
async with aiofiles.open(file_path, 'wb') as f:
await f.write(webp_page.read())
new_page = ComicPage(comic_id=new_comic.id, page_number=i, file_path=file_path)
db.session.add(new_page)
db.session.commit()
await save_pages()
return redirect(url_for('comics'))
else:
for field, errors in form.errors.items():
for error in errors:
pass
return render_template('comic_upload.html', form=form)
@upload_bp.route('/upload_post', methods=['GET', 'POST'])
@login_required