Compare commits

..

11 Commits
main ... main

30 changed files with 413 additions and 91 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "distribusi"]
path = distribusi
url = https://git.vvvvvvaria.org/crunk/distribusi

@ -1 +0,0 @@
Subproject commit e291e7497e40211c2ebd54ca32a1f4bdaed71230

0
distribusi/__init__.py Normal file
View File

236
distribusi/distribusi.py Normal file
View File

@ -0,0 +1,236 @@
import os
import magic
from PIL import Image
from distribusi.templates.page_template import html_footer, html_head
from distribusi.templates.image_templates import (
image_no_description,
image_with_description,
image_with_alttext,
image_full_figure,
)
from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES
MIME_TYPE = magic.Magic(mime=True)
def _add_alttext(full_path_image):
try:
image_filename_no_ext = os.path.splitext(full_path_image)[0]
alttext_filename = f"{image_filename_no_ext}_alttext.txt"
return _read_matching_text_file(
image_filename_no_ext, alttext_filename
)
except Exception as e:
print(f"exception {e} raised while making alttext")
return
def _add_description(full_path_image):
try:
image_filename_no_ext = os.path.splitext(full_path_image)[0]
description_filename = f"{image_filename_no_ext}_dv_description.txt"
return _read_matching_text_file(
image_filename_no_ext, description_filename
)
except Exception as e:
print(f"exception {e} raised while adding description")
return
def _read_matching_text_file(image_filename_no_ext, filename):
if not os.path.isfile(filename):
return
print(f"{image_filename_no_ext} has {filename}")
with open(filename, "r") as text_file:
return text_file.read()
def _make_thumbnail(full_path_image, name):
if full_path_image.endswith("_thumbnail.jpg"):
return
try:
size = (450, 450)
thumbnail_image = Image.open(full_path_image)
thumbnail_image.thumbnail(size)
if thumbnail_image.mode == "RGBA":
bg = Image.new("RGBA", thumbnail_image.size, (255, 255, 255))
composite = Image.alpha_composite(bg, thumbnail_image)
thumbnail_image = composite.convert("RGB")
image_filename_no_ext = os.path.splitext(full_path_image)[0]
thumbnail_filename = f"{image_filename_no_ext}_thumbnail.jpg"
thumbnail_image.save(thumbnail_filename, format="JPEG")
return os.path.basename(thumbnail_filename)
except Exception as e:
print("Thumbnailer:", e)
return
def _format_div(type_, subtype, tag, name):
id_name = name.split(".")[0].replace(" ", "_")
filename = f'<span class="filename">{name}</span>'
if "image" in type_:
html = '<div id="{}" class="{}">{}</div>'
elif "pdf" in subtype:
html = '<div id="{}" class="{}">{}' + filename + "</div>"
elif "dir" in type_ or "html" in subtype or "unkown-file" in subtype:
html = '<div id="{}" class="{}">{}</div>'
else:
html = '<div id="{}" class="{}">{}' + filename + "</div>"
return html.format(id_name, subtype, tag)
def _check_distribusi_index(index):
"""
check whether a index.html file is generated by distribusi
"""
with open(index, "r") as f:
if '<meta name="generator" content="distribusi" />' in f.read():
return True
return False
def _write_index_html(index, html, cssfile):
with open(index, "w") as index_file:
styled_html_head = html_head.format(cssfile=cssfile)
index_file.write(styled_html_head)
for line in html:
index_file.write(line + "\n")
index_file.write(html_footer)
def _handle_text_files(name, full_path, subtype):
if name.endswith(".html") or subtype == "html":
subtype = "html"
# what types of text files to expand
tag = '<section id="{}">{}</section>'.format(
name, open(full_path).read()
)
elif subtype in CODE_TYPES or name.endswith(".txt"):
# if the plain text is code,
# which types do we wrap in pre-tags?
tag = "<pre>" + open(full_path).read() + "</pre>"
else:
subtype = subtype + " unkown-file"
tag = "<a href='{}'>{}</a>"
# a = FILE_TYPES[type_]
return subtype, tag
def _handle_image_files(name, full_path):
thumbnail_filename = _make_thumbnail(full_path, name)
if thumbnail_filename is None:
return
image_alttext = _add_alttext(full_path)
image_description = _add_description(full_path)
if not image_alttext and not image_description:
return image_no_description.format(
name=name, thumbnail_filename=thumbnail_filename
)
if not image_alttext:
return image_with_description.format(
name=name,
thumbnail_filename=thumbnail_filename,
image_description=image_description,
)
if not image_description:
return image_with_alttext.format(
name=name,
thumbnail_filename=thumbnail_filename,
image_alttext=image_alttext,
)
return image_full_figure.format(
name=name,
thumbnail_filename=thumbnail_filename,
image_alttext=image_alttext,
image_description=image_description,
)
def _remove_existing_index_html(root, files):
index = os.path.join(root, "index.html")
if "index.html" in files:
try:
if check_distribusi_index(index):
os.remove(index)
except Exception as e:
print(e)
return
def _remove_hidden_files_and_folders(dirs, files):
dirs = list(filter(lambda d: not d.startswith("."), dirs))
files = list(filter(lambda f: not f.startswith("."), files))
return dirs, files
def _is_skippable_file(name, cssfile):
if "index.html" in name:
return True
if name.endswith("_thumbnail.jpg"):
return True
if name.endswith("_alttext.txt"):
return True
if name.endswith("_dv_description.txt"):
return True
if cssfile in name:
return True
def distribusify(directory, cssfile):
for root, dirs, files in os.walk(directory):
html = []
dirs, files = _remove_hidden_files_and_folders(dirs, files)
_remove_existing_index_html(root, files)
for name in sorted(files):
if _is_skippable_file(name, cssfile):
continue
full_path = os.path.join(root, name)
mime = MIME_TYPE.from_file(full_path)
type_, subtype = mime.split("/")
alttext = name
if type_ in FILE_TYPES:
match type_:
case "text":
subtype, tag = handle_text_files(
name, full_path, subtype
)
case "image":
tag = _handle_image_files(name, full_path)
if tag is None:
continue
case _:
tag = FILE_TYPES[type_].format(name, alttext)
if subtype in SUB_TYPES:
tag = SUB_TYPES[subtype]
if type_ not in FILE_TYPES and subtype not in SUB_TYPES:
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
tag = "<a href='{}'>{}</a>"
tag = tag.replace("{}", name)
html.append(_format_div(type_, subtype, tag, name))
if root != directory:
html.append('<a href="../index.html">../</a>')
for name in sorted(dirs):
tag = "<a href='{}/index.html'>{}</a>".replace("{}", name)
html.insert(0, format_div("dir", "dir", tag, "folder"))
index = os.path.join(root, "index.html")
_write_index_html(index, html, cssfile)

15
distribusi/mappings.py Normal file
View File

@ -0,0 +1,15 @@
CODE_TYPES = ["x-c", "x-shellscript", "x-python"]
FILE_TYPES = {
"image": '<img class="image" src="{}" alt="{}">',
"text": '<a href="{}" class="text">{}</a>',
"video": ("<video controls>" '<source src="{}"></video>'),
"audio": ('<audio controls class="audio">' '<source src="{}"></audio>'),
}
SUB_TYPES = {
"pdf": (
'<object data="{}" class="pdf" type="application/pdf">'
'<embed src="{}" type="application/pdf" /></object>'
)
}

View File

View File

@ -0,0 +1,4 @@
image_no_description = '<a href="{name}"><img class="thumbnail" src="{thumbnail_filename}" alt="{name}"></a>'
image_with_description = '<figure><a href="{name}"><img class="thumbnail" src="{thumbnail_filename}"></a><figcaption>{image_description}</figcaption></figure>'
image_with_alttext = '<a href="{name}"><img class="thumbnail" src="{thumbnail_filename}" alt="{image_alttext}"></a>'
image_full_figure = '<figure><a href="{name}"><img class="thumbnail" src="{thumbnail_filename}" alt="{image_alttext}"></a><figcaption>{image_description}</figcaption></figure>'

View File

@ -0,0 +1,16 @@
html_head = """\
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Generated with distribusi https://git.vvvvvvaria.org/crunk/distribusi -->
<meta name="generator" content="distribusi" />
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="{cssfile}" crossorigin="anonymous">
</head>
<body>
"""
html_footer = """\
</body>
</html>
"""

View File

@ -8,7 +8,6 @@ bleach-allowlist==1.0.3
blinker==1.7.0 blinker==1.7.0
cffi cffi
click==8.1.7 click==8.1.7
distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@3eefd6e5ca7048555d441df8c6fbf4f2e255acac
dnspython==2.1.0 dnspython==2.1.0
email-validator==1.1.3 email-validator==1.1.3
Flask==3.0.3 Flask==3.0.3

View File

@ -1,3 +1,3 @@
from setuptools import find_packages, setup from setuptools import find_packages, setup
setup(name="library", version="1.0", packages=find_packages()) setup(name="dsitribusi-verse", version="1.0", packages=find_packages())

View File

@ -2,7 +2,7 @@ import os
import shutil import shutil
from flask import render_template, Blueprint from flask import render_template, Blueprint
from flask_login import current_user, login_required from flask_login import login_required
from sqlalchemy.exc import ( from sqlalchemy.exc import (
DatabaseError, DatabaseError,
DataError, DataError,

View File

@ -51,6 +51,8 @@ def create_app():
def inject_title(): def inject_title():
return dict(title=APP.config["title"]) return dict(title=APP.config["title"])
APP.logger.setLevel("INFO")
APP.logger.info("Distribusi-verse successfully started")
return APP return APP

View File

@ -15,8 +15,6 @@ from sqlalchemy.exc import (
InterfaceError, InterfaceError,
InvalidRequestError, InvalidRequestError,
) )
import piexif
from PIL import Image
from app import db from app import db
from models.distribusi_model import Distribusis from models.distribusi_model import Distribusis
from models.distribusi_file_model import DistribusiFiles from models.distribusi_file_model import DistribusiFiles
@ -114,7 +112,6 @@ def get_distribusi_file_forms(distribusi_id):
def save_described_file_to_db(describe_form, distribusi_file): def save_described_file_to_db(describe_form, distribusi_file):
try: try:
if describe_form.description.data: if describe_form.description.data:
print(distribusi_file.id)
distribusi_file.description = describe_form.description.data distribusi_file.description = describe_form.description.data
if describe_form.alttext.data: if describe_form.alttext.data:
distribusi_file.alttext = describe_form.alttext.data distribusi_file.alttext = describe_form.alttext.data
@ -143,7 +140,8 @@ def save_described_file_to_db(describe_form, distribusi_file):
def add_alttext_to_file(describe_form, distribusi_file): def add_alttext_to_file(describe_form, distribusi_file):
if not describe_form.alttext.data: if not describe_form.alttext.data:
return return
filename_no_ext = os.path.splitext(distribusi_file.path)[0] filename = os.path.join("stash", distribusi_file.path)
filename_no_ext = os.path.splitext(filename)[0]
with open(f"{filename_no_ext}_alttext.txt", "w") as alttext_file: with open(f"{filename_no_ext}_alttext.txt", "w") as alttext_file:
alttext_file.write(describe_form.alttext.data) alttext_file.write(describe_form.alttext.data)
return return
@ -152,7 +150,8 @@ def add_alttext_to_file(describe_form, distribusi_file):
def add_description_to_file(describe_form, distribusi_file): def add_description_to_file(describe_form, distribusi_file):
if not describe_form.description.data: if not describe_form.description.data:
return return
filename_no_ext = os.path.splitext(distribusi_file.path)[0] filename = os.path.join("stash", distribusi_file.path)
filename_no_ext = os.path.splitext(filename)[0]
with open( with open(
f"{filename_no_ext}_dv_description.txt", "w" f"{filename_no_ext}_dv_description.txt", "w"
) as description_file: ) as description_file:

View File

@ -1,7 +1,7 @@
"""Describe File Form to describe files in the distribusi archive""" """Describe File Form to describe files in the distribusi archive"""
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, validators from wtforms import StringField, SubmitField
from wtforms.validators import Length from wtforms.validators import Length
from wtforms.widgets import TextArea from wtforms.widgets import TextArea
@ -39,10 +39,3 @@ class DescribeFilesForm(FlaskForm):
self.searchtags.id = f"searchtags-{id}" self.searchtags.id = f"searchtags-{id}"
self.description.id = f"description-{id}" self.description.id = f"description-{id}"
self.save.id = f"save-{id}" self.save.id = f"save-{id}"
# def StringFieldWithId(form_name, **kwargs):
# name = kwargs.get('name', 'Bar')
# return wtf.StringField(name, render_kw={
# 'id': f'{}{}'.format(form_name, name.lower(),
# **kwargs.get('render_kw', {})})

View File

@ -31,13 +31,13 @@
{% for id, describe_form in distribusi_file_forms.items() %} {% for id, describe_form in distribusi_file_forms.items() %}
<div class="distribusi_file"> <div class="distribusi_file">
{% if describe_form.type == "image" %} {% if describe_form.type == "image" %}
<img src="{{describe_form.file_path}}" alt="" data-src="{{describe_form.file_path}}" loading="lazy"/> <img src="{{ url_for('shortstashurl')}}/{{describe_form.file_path}}" alt="" data-src="{{ url_for('shortstashurl')}}/{{describe_form.file_path}}" loading="lazy"/>
{% elif describe_form.type == "video" %} {% elif describe_form.type == "video" %}
<video src="{{describe_form.file_path}}" preload="auto" alt="" controls loading="lazy"></video> <video src="{{ url_for('shortstashurl')}}/{{describe_form.file_path}}" preload="auto" alt="" controls loading="lazy"></video>
{% elif describe_form.type == "audio" %} {% elif describe_form.type == "audio" %}
<audio src="{{describe_form.file_path}}" preload="auto" alt="" controls loading="lazy"> </audio> <audio src="{{ url_for('shortstashurl')}}/{{describe_form.file_path}}" preload="auto" alt="" controls loading="lazy"> </audio>
{% else %} {% else %}
<a href="{{describe_form.file_path}}">file: {{describe_form.file_path}}</a> <a href="{{ url_for('shortstashurl')}}/{{describe_form.file_path}}">file: {{describe_form.file_path}}</a>
{% endif %} {% endif %}
<form id={{id}} method="POST" enctype="multipart/form-data" action="{{ url_for('describer.describe_file', file_id=id) }}"> <form id={{id}} method="POST" enctype="multipart/form-data" action="{{ url_for('describer.describe_file', file_id=id) }}">
{{ describe_form.csrf_token }} {{ describe_form.csrf_token }}

View File

@ -4,7 +4,7 @@ import magic
from distribusi.mappings import FILE_TYPES from distribusi.mappings import FILE_TYPES
from models.distribusi_model import Distribusis from models.distribusi_model import Distribusis
from models.distribusi_file_model import DistribusiFiles from models.distribusi_file_model import DistribusiFiles
from app import create_app, get_app, db from app import get_app, db
from sqlalchemy.exc import ( from sqlalchemy.exc import (
DatabaseError, DatabaseError,
DataError, DataError,
@ -30,14 +30,14 @@ def _get_distribusi_from_path(path):
def _add_distribusi_file_to_db(distribusi, full_path, type): def _add_distribusi_file_to_db(distribusi, full_path, type):
app = get_app() app = get_app()
app.logger.info(f"adding file to database: {full_path} type: {type}") app.logger.info(f"Adding file to database: {full_path} type: {type}")
distribusi_file = DistribusiFiles.query.filter_by(path=full_path).first() distribusi_file = DistribusiFiles.query.filter_by(path=full_path).first()
if distribusi_file is not None: if distribusi_file is not None:
app.logger.error(f"File already in database: {full_path}") app.logger.error(f"File already in database: {full_path}")
return return
try: try:
new_distribusi_file = DistribusiFiles( new_distribusi_file = DistribusiFiles(
path=full_path, path=full_path.lstrip("stash/"),
type=type, type=type,
distribusi=distribusi.id, distribusi=distribusi.id,
) )

View File

@ -12,7 +12,7 @@ from sqlalchemy.exc import (
) )
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from app import db from app import db, APP
from distribusikan.distribusis_info import DistribusisInfo from distribusikan.distribusis_info import DistribusisInfo
from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.distribusiform import DistribusiForm
from distribusikan.forms.editorform import EditorForm from distribusikan.forms.editorform import EditorForm
@ -92,8 +92,7 @@ def copy_public_to_user_folder(editorform, publicfolder, newcssfolder):
copycssfile = os.path.join( copycssfile = os.path.join(
publicfolder, f"{secure_filename(editorform.cssname.data)}.css" publicfolder, f"{secure_filename(editorform.cssname.data)}.css"
) )
print(f"copying file: {copycssfile}") APP.logger.info(f"copying file:{copycssfile} to folder:{newcssfolder}")
print(f"to folder: {newcssfolder}")
shutil.copy(copycssfile, newcssfolder) shutil.copy(copycssfile, newcssfolder)

View File

@ -10,7 +10,7 @@ from sqlalchemy.exc import (
InvalidRequestError, InvalidRequestError,
) )
from app import db from app import db, APP
from distribusikan.distribusis_info import DistribusisInfo from distribusikan.distribusis_info import DistribusisInfo
from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.distribusiform import DistribusiForm
from distribusikan.forms.publicthemeform import PublicThemeForm from distribusikan.forms.publicthemeform import PublicThemeForm
@ -18,6 +18,7 @@ from distribusikan.forms.selectorform import SelectorForm
from distribusikan.forms.themeform import ThemeForm from distribusikan.forms.themeform import ThemeForm
from distribusikan.forms.uploadform import UploadForm from distribusikan.forms.uploadform import UploadForm
from models.distribusi_model import Distribusis from models.distribusi_model import Distribusis
from models.distribusi_file_model import DistribusiFiles
from models.user_model import User from models.user_model import User
# UserPengguna # UserPengguna
@ -65,7 +66,7 @@ def auto_fill_in_upload_form(uploadform, current_distribusi):
def select_new_distribusi(): def select_new_distribusi():
print("make a new distribusi") APP.logger.info("make a new distribusi")
select_current_distribusi("new") select_current_distribusi("new")
@ -79,12 +80,11 @@ def select_describe_distribusi(distribusiname):
def select_update_distribusi(distribusiname): def select_update_distribusi(distribusiname):
print(f"Update this distribusi {distribusiname}")
select_current_distribusi(distribusiname) select_current_distribusi(distribusiname)
def delete_distribusi(distribusiname): def delete_distribusi(distribusiname):
print(f"delete this distribusi {distribusiname}") APP.logger.info(f"attempt to delete distribusi:{distribusiname}")
selectorform = SelectorForm() selectorform = SelectorForm()
try: try:
user = User.query.filter_by(email=current_user.email).first() user = User.query.filter_by(email=current_user.email).first()
@ -94,29 +94,45 @@ def delete_distribusi(distribusiname):
if distribusi.userid is user.id: if distribusi.userid is user.id:
db.session.delete(distribusi) db.session.delete(distribusi)
db.session.commit() db.session.commit()
userfolder = os.path.join("stash", distribusi.distribusiname)
if os.path.exists(userfolder):
shutil.rmtree(userfolder)
cssfolder = os.path.join(
"themes/userthemes", distribusi.distribusiname
)
if os.path.exists(cssfolder):
shutil.rmtree(cssfolder)
if distribusi.publictheme is not None:
publicthemefolder = os.path.join(
"themes/publicthemes", distribusi.distribusiname
)
if os.path.exists(publicthemefolder):
shutil.rmtree(publicthemefolder)
# SelectField error is list is a tuple?? why??
# selectorform.distribusis.errors.append("Distribusi deleted!")
except (InvalidRequestError, DataError, InterfaceError, DatabaseError): except (InvalidRequestError, DataError, InterfaceError, DatabaseError):
db.session.rollback() db.session.rollback()
# selectorform.distribusis.errors.append("Unknown error occured!")
flash("An error occured !", "danger") flash("An error occured !", "danger")
_delete_distribusi_files(distribusi.distribusiname)
APP.logger.info(f"deleted distribusi:{distribusiname}")
return selectorform return selectorform
def _delete_distribusi_files(distribusiname):
userfolder = os.path.join("stash", distribusiname)
if os.path.exists(userfolder):
shutil.rmtree(userfolder)
cssfolder = os.path.join("themes/userthemes", distribusiname)
if os.path.exists(cssfolder):
shutil.rmtree(cssfolder)
distribusi = Distribusis.query.filter_by(
distribusiname=distribusiname
).first()
if distribusi.publictheme is not None:
publicthemefolder = os.path.join("themes/publicthemes", distribusiname)
if os.path.exists(publicthemefolder):
shutil.rmtree(publicthemefolder)
def _delete_distribusi_database_files(distribusiname):
try:
distribusi = Distribusis.query.filter_by(
distribusiname=distribusiname
).first()
distribusi_db_files = DistribusiFiles.query.filter_by(
distribusi=distribusi
)
db.session.delete(distribusi_db_files)
db.session.commit()
except (InvalidRequestError, DataError, InterfaceError, DatabaseError):
db.session.rollback()
def select_current_distribusi(distribusiname): def select_current_distribusi(distribusiname):
if not current_user.is_authenticated: if not current_user.is_authenticated:
return return

View File

@ -2,8 +2,6 @@ import os
import shutil import shutil
import zipfile import zipfile
# Tada!
from distribusi.cli import build_argparser
from distribusi.distribusi import distribusify from distribusi.distribusi import distribusify
from flask import flash, redirect, render_template, url_for from flask import flash, redirect, render_template, url_for
from flask_login import current_user from flask_login import current_user
@ -14,7 +12,7 @@ from sqlalchemy.exc import (
InvalidRequestError, InvalidRequestError,
) )
from app import db from app import db, APP
from distribusikan.add_files_to_describer import add_distribusi_files_to_db from distribusikan.add_files_to_describer import add_distribusi_files_to_db
from distribusikan.distribusi_selector import selector_visible from distribusikan.distribusi_selector import selector_visible
from distribusikan.distribusis_info import DistribusisInfo from distribusikan.distribusis_info import DistribusisInfo
@ -96,10 +94,10 @@ def get_css_file(distribusi):
def run_distribusi(userfolder, cssfile): def run_distribusi(userfolder, cssfile):
print(f"Run distribusi on this folder: {userfolder} with css:{cssfile}") APP.logger.info(
parser = build_argparser() f"Run distribusi on this folder: {userfolder} with css:{cssfile}"
args = parser.parse_args(["-t", "-a", "--menu-with-index", "-s", cssfile]) )
distribusify(args, userfolder) distribusify(userfolder, cssfile)
def set_distribusi_to_visible(distribusi, user): def set_distribusi_to_visible(distribusi, user):

View File

@ -4,7 +4,6 @@ from wtforms import (
SelectField, SelectField,
StringField, StringField,
SubmitField, SubmitField,
TextAreaField,
validators, validators,
) )
from wtforms.validators import ( from wtforms.validators import (

View File

@ -79,7 +79,9 @@ def upload_updates_files(uploadfolder):
db.session.commit() db.session.commit()
except (InvalidRequestError, DataError, InterfaceError, DatabaseError): except (InvalidRequestError, DataError, InterfaceError, DatabaseError):
db.session.rollback() db.session.rollback()
uploadform.sitename.errors.append("Something went wrong!") uploadform.sitename.errors.append(
"Something went wrong with the database!"
)
zipfilename = "{}.zip".format(distribusi.distribusiname) zipfilename = "{}.zip".format(distribusi.distribusiname)
zipfile = uploadform.zipfile.data zipfile = uploadform.zipfile.data

View File

@ -1,9 +1,7 @@
"""SearchForm to search files and distribusis in the distribusi archive""" """SearchForm to search files and distribusis in the distribusi archive"""
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, validators from wtforms import StringField, SubmitField
from wtforms.validators import Length
from wtforms.widgets import TextArea
class SearchForm(FlaskForm): class SearchForm(FlaskForm):

View File

@ -20,12 +20,16 @@ SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata"))
def searchpage(): def searchpage():
searchform = SearchForm() searchform = SearchForm()
found_distribusis = [] found_distribusis = []
found_distribusi_files = []
if searchform.validate_on_submit(): if searchform.validate_on_submit():
found_distribusis = search(searchform.searchfield.data) found_distribusis, found_distribusi_files = search(
searchform.searchfield.data
)
template = render_template( template = render_template(
"search.html", "search.html",
searchform=searchform, searchform=searchform,
found_distribusis=found_distribusis, found_distribusis=found_distribusis,
found_distribusi_files=found_distribusi_files,
) )
return template return template
@ -36,7 +40,15 @@ def search(searchinput):
with ix.searcher() as searcher: with ix.searcher() as searcher:
query = QueryParser("content", ix.schema).parse(searchinput) query = QueryParser("content", ix.schema).parse(searchinput)
search_results = searcher.search(query) search_results = searcher.search(query)
found_distribusis = []
for result in search_results: for result in search_results:
print(result["title"])
print(result["path"])
found_distribusis = []
found_distribusi_files = []
for result in search_results:
if result["path"] == "/a":
found_distribusis.append(result["title"]) found_distribusis.append(result["title"])
return found_distribusis if result["path"] == "/b":
found_distribusi_files.append(result["title"])
return found_distribusis, found_distribusi_files

View File

@ -1,8 +1,8 @@
import os import os
from whoosh.fields import * from whoosh.fields import *
from whoosh.index import create_in from whoosh.index import create_in, open_dir
from whoosh.qparser import QueryParser
from models.distribusi_model import Distribusis from models.distribusi_model import Distribusis
from models.distribusi_file_model import DistribusiFiles
import flask_apscheduler import flask_apscheduler
@ -15,21 +15,26 @@ def init_search_index(APP):
scheduler.api_enabled = False scheduler.api_enabled = False
scheduler.init_app(APP) scheduler.init_app(APP)
scheduler.start() scheduler.start()
index_distribusis(APP)
index_distribusi_files(APP)
@scheduler.task("interval", id="update", minutes=60)
def update_search_index():
index_distribusis(APP)
index_distribusi_files(APP)
def index_distribusis(APP):
schema = Schema( schema = Schema(
title=TEXT(stored=True), path=ID(stored=True), content=TEXT title=TEXT(stored=True), path=ID(stored=True), content=TEXT
) )
ix = create_in(SEARCH_DATA_DIR, schema) ix = create_in(SEARCH_DATA_DIR, schema)
writer = ix.writer() writer = ix.writer()
index_distribusis(APP, writer)
index_distribusi_files(APP, writer)
writer.commit(optimize=True)
@scheduler.task("interval", id="update", minutes=60)
def update_search_index():
ix = open_dir(SEARCH_DATA_DIR)
update_writer = ix.writer()
index_distribusis(APP, update_writer)
index_distribusi_files(APP, update_writer)
update_writer.commit(optimize=True)
def index_distribusis(APP, writer):
distribusis = _visible_distribusis(APP) distribusis = _visible_distribusis(APP)
for distribusi in distribusis: for distribusi in distribusis:
writer.add_document( writer.add_document(
@ -37,11 +42,19 @@ def index_distribusis(APP):
path="/a", path="/a",
content=distribusi.description, content=distribusi.description,
) )
writer.commit()
def index_distribusi_files(APP): def index_distribusi_files(APP, writer):
APP.logger.info("searching distribusi files not implemented yet.") with APP.app_context():
for distribusi_file in DistribusiFiles.query.all():
APP.logger.info(
f"adding distribusi file {distribusi_file.path} to search index"
)
writer.add_document(
title=distribusi_file.path,
path="/b",
content=distribusi_file.description,
)
def _visible_distribusis(APP): def _visible_distribusis(APP):

View File

@ -19,5 +19,13 @@
<a href='{{ url_for('shortstashurl')}}/{{found_distribusi}}/index.html'>{{found_distribusi}}</a> <a href='{{ url_for('shortstashurl')}}/{{found_distribusi}}/index.html'>{{found_distribusi}}</a>
{% endfor %} {% endfor %}
</div> </div>
<div class="searchresults">
{% for found_distribusi_file in found_distribusi_files %}
<a href="{{ url_for('shortstashurl')}}/{{found_distribusi_file}}">
<img src="{{ url_for('shortstashurl')}}/{{found_distribusi_file}}" alt="">
{{found_distribusi_file}}
</a>
{% endfor %}
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -10,7 +10,7 @@ from flask import (
session, session,
url_for, url_for,
) )
from flask_login import current_user, login_required, logout_user from flask_login import login_required, logout_user
from flask_wtf.csrf import CSRFError from flask_wtf.csrf import CSRFError
from admin import is_adminuser from admin import is_adminuser

View File

@ -8,7 +8,10 @@ body
line-height: 1.1; line-height: 1.1;
} }
img {
width: 100%;
height: 100%;
}
#mainworkflow #mainworkflow
{ {
@ -121,13 +124,15 @@ input[type="submit"]:disabled:focus {
to { width: 55%; } to { width: 55%; }
} }
#fancyboi { #fancyboi {
font-size: 24px;
width: 55%; width: 55%;
padding: 0.5em; padding: 0.5em;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
animation: reveal 4s linear; animation: reveal 2s linear;
text-overflow: "█"; text-overflow: "█";
background-color: #9de457; background-color: #9de457;
margin: auto;
} }
#fancyboi::after { #fancyboi::after {
content: "█"; content: "█";
@ -139,6 +144,7 @@ div.maincontent{
width: 55%; width: 55%;
border: 3px #9de457; border: 3px #9de457;
margin-top: 0.5em; margin-top: 0.5em;
margin: auto;
padding: 0.5em; padding: 0.5em;
border-style: outset; border-style: outset;
} }

View File

@ -39,7 +39,6 @@ def LoginUser():
flash("Logged in successfully.", "success") flash("Logged in successfully.", "success")
next = request.args.get("next") next = request.args.get("next")
if next is not None and not is_safe_url(next): # noqa: F821 if next is not None and not is_safe_url(next): # noqa: F821
print(next)
return abort(400) return abort(400)
print("index") print("index")
return redirect(next or url_for("index")) return redirect(next or url_for("index"))

View File

@ -1,20 +1,32 @@
{% block menu %} {% block menu %}
<button onclick="filterSelection('all')" id="removefilter">Remove filter</button> <button onclick="filterSelection('all')" id="removefilter">Remove filter</button>
<div class="dropdown"> <div class="dropdown">
<button id="Year" class="dropbtn">Year</button> <nav class="button-navigation">
<button id="Year" class="dropbtn" aria-haspopup="true">Year</button>
<div class="dropdown-content"> <div class="dropdown-content">
<ul>
{% for year in years %} {% for year in years %}
<li>
<button type="button" name="button" onclick="filterSelection('{{ year[0] }}', '{{ year[1] }}', 'Year')" >{{ year[1] }}</button> <button type="button" name="button" onclick="filterSelection('{{ year[0] }}', '{{ year[1] }}', 'Year')" >{{ year[1] }}</button>
</li>
{% endfor %} {% endfor %}
</ul>
</div> </div>
</nav>
</div> </div>
<div class="dropdown"> <div class="dropdown">
<button id="Category" class="dropbtn">Category</button> <nav class="button-navigation">
<button id="Category" class="dropbtn" aria-haspopup="true">Category</button>
<div class="dropdown-content"> <div class="dropdown-content">
<ul>
{% for category in categories %} {% for category in categories %}
<li>
<button type="button" name="button" onclick="filterSelection('{{ category[0] }}', '{{ category[1] }}', 'Category')" >{{ category[1] }}</button> <button type="button" name="button" onclick="filterSelection('{{ category[0] }}', '{{ category[1] }}', 'Category')" >{{ category[1] }}</button>
</li>
{% endfor %} {% endfor %}
</ul>
</div> </div>
</nav>
</div> </div>
<input id="tagsearch" type="text" placeholder="Search.."> <input id="tagsearch" type="text" placeholder="Search..">
{% endblock menu %} {% endblock menu %}

View File

@ -39,9 +39,9 @@
</div> </div>
</div> </div>
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<h2 id="fancyboi"> Hi {{ current_user.username }}!</h2> <h1 id="fancyboi"> Hi {{ current_user.username }}!</h1>
{% else %} {% else %}
<h2 id="fancyboi"> Welcome to distribusi-verse</h2> <h1 id="fancyboi"> Welcome to the Varia Archive </h1>
{% endif %} {% endif %}
<div class="maincontent"> <div class="maincontent">
<p>Distribusi is a content management system for the web that produces static index pages based on folders in the files system. It is inspired by the automatic index functions featured in several popular web servers. Distribusi works by traversing the file system and directory hierarchy to automatically list all the files in the directory, detect the file types and providing them with relevant html classes and tags for easy styling. <p>Distribusi is a content management system for the web that produces static index pages based on folders in the files system. It is inspired by the automatic index functions featured in several popular web servers. Distribusi works by traversing the file system and directory hierarchy to automatically list all the files in the directory, detect the file types and providing them with relevant html classes and tags for easy styling.