From e4777cf7a6b1b6697abd636ed582626cb4f168f9 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Sun, 25 Jun 2023 09:24:44 +0200 Subject: [PATCH 1/2] Redirect logged-in users --- partitioncloud/__init__.py | 2 +- partitioncloud/modules/auth.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/partitioncloud/__init__.py b/partitioncloud/__init__.py index f3512bd..e313f98 100644 --- a/partitioncloud/__init__.py +++ b/partitioncloud/__init__.py @@ -82,9 +82,9 @@ def add_user(): return render_template("auth/register.html", albums=get_all_albums(), user=current_user) -# Automatically close db after each request @app.after_request def after_request(response): + """Automatically close db after each request""" if ('db' in g) and (g.db is not None): g.db.close() return response diff --git a/partitioncloud/modules/auth.py b/partitioncloud/modules/auth.py index ad41d89..ad2bc01 100644 --- a/partitioncloud/modules/auth.py +++ b/partitioncloud/modules/auth.py @@ -38,6 +38,19 @@ def login_required(view): return wrapped_view +def anon_required(view): + """View decorator that redirects authenticated users to the index.""" + + @functools.wraps(view) + def wrapped_view(**kwargs): + if g.user is not None: + return redirect(url_for("albums.index")) + + return view(**kwargs) + + return wrapped_view + + def admin_required(view): """View decorator that redirects anonymous users to the login page.""" @@ -72,6 +85,7 @@ def load_logged_in_user(): @bp.route("/register", methods=("GET", "POST")) +@anon_required def register(): """Register a new user. Validates that the username is not already taken. Hashes the @@ -115,6 +129,7 @@ def register(): @bp.route("/login", methods=("GET", "POST")) +@anon_required def login(): """Log in a registered user by adding the user id to the session.""" if request.method == "POST": From 08908ffdf749780890c4aca4e1b4a7d483fe5f17 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Mon, 28 Aug 2023 14:14:57 +0200 Subject: [PATCH 2/2] search: Multithreaded the downloads search: Thumbnails are now created on-demand --- partitioncloud/__init__.py | 30 ++++++++++++++- partitioncloud/modules/search.py | 63 ++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/partitioncloud/__init__.py b/partitioncloud/__init__.py index e313f98..da1dc38 100644 --- a/partitioncloud/__init__.py +++ b/partitioncloud/__init__.py @@ -4,12 +4,12 @@ Main file """ import os -from flask import Flask, g, redirect, render_template, request, send_file, flash, session +from flask import Flask, g, redirect, render_template, request, send_file, flash, session, abort from werkzeug.security import generate_password_hash from .modules.utils import User, Album, get_all_albums from .modules import albums, auth, partition, admin -from .modules.auth import admin_required +from .modules.auth import admin_required, login_required from .modules.db import get_db app = Flask(__name__) @@ -82,6 +82,32 @@ def add_user(): return render_template("auth/register.html", albums=get_all_albums(), user=current_user) +@app.route("/static/search-thumbnails/.jpg") +@login_required +def search_thumbnail(uuid): + db = get_db() + partition = db.execute( + """ + SELECT uuid, url FROM search_results + WHERE uuid = ? + """, + (uuid,) + ).fetchone() + + if partition is None: + abort(404) + if not os.path.exists(os.path.join(app.static_folder, "search-thumbnails", f"{uuid}.jpg")): + os.system( + f'/usr/bin/convert -thumbnail\ + "178^>" -background white -alpha \ + remove -crop 178x178+0+0 \ + partitioncloud/search-partitions/{uuid}.pdf[0] \ + partitioncloud/static/search-thumbnails/{uuid}.jpg' + ) + + return send_file(os.path.join(app.static_folder, "search-thumbnails", f"{uuid}.jpg")) + + @app.after_request def after_request(response): """Automatically close db after each request""" diff --git a/partitioncloud/modules/search.py b/partitioncloud/modules/search.py index 3de45e3..c6baf01 100644 --- a/partitioncloud/modules/search.py +++ b/partitioncloud/modules/search.py @@ -4,6 +4,7 @@ Module implémentant la recherche de partitions par mots-clés """ from uuid import uuid4 import urllib.request +import threading import os import googlesearch @@ -40,6 +41,18 @@ def local_search(query, partitions): return sorted_partitions[:min(5,len(sorted_partitions))] +def download_search_result(element): + uuid = element["uuid"] + url = element["url"] + + try: + urllib.request.urlretrieve(url, f"partitioncloud/search-partitions/{uuid}.pdf") + + except (urllib.error.HTTPError, urllib.error.URLError) as e: + with open(f"partitioncloud/search-partitions/{uuid}.pdf",'a') as f: + pass # Create empty file + + def online_search(query, num_queries): """ Renvoie les 3 résultats les plus pertinents depuis google @@ -65,35 +78,45 @@ def online_search(query, num_queries): (uuid, element,) ) db.commit() - urllib.request.urlretrieve(element, f"partitioncloud/search-partitions/{uuid}.pdf") - os.system( - f'/usr/bin/convert -thumbnail\ - "178^>" -background white -alpha \ - remove -crop 178x178+0+0 \ - partitioncloud/search-partitions/{uuid}.pdf[0] \ - partitioncloud/static/search-thumbnails/{uuid}.jpg' - ) partitions.append( { "name": element.split("://")[1].split("/")[0], - "uuid": uuid + "uuid": uuid, + "url": element } ) break except db.IntegrityError: pass - except (urllib.error.HTTPError, urllib.error.URLError) as e: - print(e, element) - db.execute( - """ - DELETE FROM search_results - WHERE uuid = ? - """, - (uuid,) - ) - db.commit() - break + + threads = [threading.Thread(target=download_search_result, args=(elem,)) for elem in partitions] + + for thread in threads: + thread.start() + + for thread in threads: + thread.join() + + for element in partitions: + pass + uuid = element["uuid"] + url = element["url"] + if os.stat(f"partitioncloud/search-partitions/{uuid}.pdf").st_size == 0: + print("An error occured", url) + db.execute( + """ + DELETE FROM search_results + WHERE uuid = ? + """, + (uuid,) + ) + db.commit() + + os.remove(f"partitioncloud/search-partitions/{uuid}.pdf") + + partitions.remove(element) + return partitions