mirror of
https://github.com/partitioncloud/partitioncloud-server.git
synced 2025-02-02 13:49:40 +01:00
Compare commits
10 Commits
6f5031623c
...
5a7c3ed09d
Author | SHA1 | Date | |
---|---|---|---|
5a7c3ed09d | |||
56d01ee3e2 | |||
fb13e396e5 | |||
bb59dfe992 | |||
9baae929cd | |||
6ad1192cec | |||
93c8078bdb | |||
10621d70c7 | |||
64d06dcfe2 | |||
ec3a7d4523 |
14
.gitignore
vendored
14
.gitignore
vendored
@ -2,15 +2,11 @@
|
||||
**/__pycache__
|
||||
|
||||
# config
|
||||
.vscode
|
||||
.vscode/
|
||||
|
||||
# data
|
||||
instance
|
||||
partitioncloud/partitions
|
||||
partitioncloud/search-partitions
|
||||
partitioncloud/static/thumbnails
|
||||
partitioncloud/static/search-thumbnails
|
||||
partitioncloud/attachments
|
||||
instance/
|
||||
|
||||
.venv
|
||||
backups
|
||||
|
||||
.venv/
|
||||
backups/
|
10
make.sh
10
make.sh
@ -7,11 +7,11 @@ init () {
|
||||
mkdir -p "$INSTANCE_PATH/partitions"
|
||||
mkdir -p "$INSTANCE_PATH/attachments"
|
||||
mkdir -p "$INSTANCE_PATH/search-partitions"
|
||||
mkdir -p "$INSTANCE_PATH/static/thumbnails"
|
||||
mkdir -p "$INSTANCE_PATH/static/search-thumbnails"
|
||||
mkdir -p "$INSTANCE_PATH/cache/thumbnails"
|
||||
mkdir -p "$INSTANCE_PATH/cache/search-thumbnails"
|
||||
|
||||
if ! test -f "$INSTANCE_PATH/config.py"; then
|
||||
echo "SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex())')" > "$INSTANCE_PATH/config.py"
|
||||
echo "SECRET_KEY=\"$(python3 -c 'import secrets; print(secrets.token_hex())')\"" > "$INSTANCE_PATH/config.py"
|
||||
fi
|
||||
|
||||
if test -f "$INSTANCE_PATH/partitioncloud.sqlite"; then
|
||||
@ -43,9 +43,9 @@ usage () {
|
||||
}
|
||||
|
||||
if [[ $1 && $(type "$1") = *"is a"*"function"* || $(type "$1") == *"est une fonction"* ]]; then
|
||||
# Import config
|
||||
# Import config
|
||||
source "default_config.py"
|
||||
[[ ! -x" $INSTANCE_PATH/config.py" ]] && source "$INSTANCE_PATH/config.py"
|
||||
[[ ! -x "$INSTANCE_PATH/config.py" ]] && source "$INSTANCE_PATH/config.py"
|
||||
$1 ${*:2} # Call the function
|
||||
else
|
||||
usage
|
||||
|
@ -12,7 +12,7 @@ from flask import Flask, g, redirect, render_template, request, send_file, flash
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from .modules.utils import User, Album, get_all_albums
|
||||
from .modules import albums, auth, partition, admin, groupe
|
||||
from .modules import albums, auth, partition, admin, groupe, thumbnails
|
||||
from .modules.auth import admin_required, login_required
|
||||
from .modules.db import get_db
|
||||
|
||||
@ -39,8 +39,9 @@ def load_config():
|
||||
app.config.from_object(user_config)
|
||||
|
||||
if os.path.abspath(app.config["INSTANCE_PATH"]) != app.instance_path:
|
||||
print("[ERROR] Using two different instance path. \
|
||||
\nPlease modify INSTANCE_PATH only in default_config.py and remove it from $INSTANCE_PATH/config.py")
|
||||
print(("[ERROR] Using two different instance path.\n"
|
||||
"Please modify INSTANCE_PATH only in default_config.py ",
|
||||
"and remove it from $INSTANCE_PATH/config.py"))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("[WARNING] Using default config")
|
||||
@ -66,6 +67,7 @@ app.register_blueprint(admin.bp)
|
||||
app.register_blueprint(groupe.bp)
|
||||
app.register_blueprint(albums.bp)
|
||||
app.register_blueprint(partition.bp)
|
||||
app.register_blueprint(thumbnails.bp)
|
||||
|
||||
__version__ = get_version()
|
||||
|
||||
@ -107,35 +109,6 @@ def add_user():
|
||||
return render_template("auth/register.html", albums=get_all_albums(), user=current_user)
|
||||
|
||||
|
||||
@app.route("/static/search-thumbnails/<uuid>.jpg")
|
||||
@login_required
|
||||
def search_thumbnail(uuid):
|
||||
"""
|
||||
Renvoie l'apercu d'un résultat de recherche
|
||||
"""
|
||||
db = get_db()
|
||||
part = db.execute(
|
||||
"""
|
||||
SELECT uuid, url FROM search_results
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(uuid,)
|
||||
).fetchone()
|
||||
|
||||
if part 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 \
|
||||
{app.instance_path}/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.before_request
|
||||
def before_request():
|
||||
"""Set cookie max age to 31 days"""
|
||||
|
@ -299,13 +299,6 @@ def add_partition(album_uuid):
|
||||
partition_path
|
||||
)
|
||||
|
||||
os.system(
|
||||
f'/usr/bin/convert -thumbnail\
|
||||
"178^>" -background white -alpha \
|
||||
remove -crop 178x178+0+0 \
|
||||
{partition_path}[0] \
|
||||
partitioncloud/static/thumbnails/{partition_uuid}.jpg'
|
||||
)
|
||||
db.commit()
|
||||
|
||||
album.add_partition(partition_uuid)
|
||||
|
@ -133,8 +133,8 @@ class Album():
|
||||
attachment.delete(instance_path)
|
||||
|
||||
os.remove(f"{instance_path}/partitions/{partition['uuid']}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg")
|
||||
if os.path.exists(f"{instance_path}/cache/thumbnails/{partition['uuid']}.jpg"):
|
||||
os.remove(f"{instance_path}/cache/thumbnails/{partition['uuid']}.jpg")
|
||||
|
||||
partitions = db.execute(
|
||||
"""
|
||||
|
@ -43,8 +43,8 @@ class Partition():
|
||||
db.commit()
|
||||
|
||||
os.remove(f"{instance_path}/partitions/{self.uuid}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{self.uuid}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{self.uuid}.jpg")
|
||||
if os.path.exists(f"{instance_path}/cache/thumbnails/{self.uuid}.jpg"):
|
||||
os.remove(f"{instance_path}/cache/thumbnails/{self.uuid}.jpg")
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
|
@ -150,14 +150,11 @@ def flush_cache(instance_path):
|
||||
).fetchall()
|
||||
for element in expired_cache:
|
||||
uuid = element["uuid"]
|
||||
try:
|
||||
if os.path.exists(f"{instance_path}/search-partitions/{uuid}.pdf"):
|
||||
os.remove(f"{instance_path}/search-partitions/{uuid}.pdf")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
os.remove(f"partitioncloud/static/search-thumbnails/{uuid}.jpg")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
if os.path.exists(f"{instance_path}/cache/search-thumbnails/{uuid}.jpg"):
|
||||
os.remove(f"{instance_path}/cache/search-thumbnails/{uuid}.jpg")
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
|
57
partitioncloud/modules/thumbnails.py
Normal file
57
partitioncloud/modules/thumbnails.py
Normal file
@ -0,0 +1,57 @@
|
||||
"""
|
||||
Thumbnails
|
||||
"""
|
||||
import os
|
||||
|
||||
from flask import current_app, abort, Blueprint, send_file
|
||||
|
||||
from .auth import login_required
|
||||
|
||||
bp = Blueprint("thumbnails", __name__, url_prefix="/thumbnails")
|
||||
|
||||
|
||||
def generate_thumbnail(source, dest):
|
||||
"""
|
||||
Generates a thumbnail with 'convert' (ImageMagick)
|
||||
"""
|
||||
os.system(
|
||||
f'/usr/bin/convert -thumbnail\
|
||||
"178^>" -background white -alpha \
|
||||
remove -crop 178x178+0+0 \
|
||||
{source}[0] \
|
||||
{dest}'
|
||||
)
|
||||
|
||||
def serve_thumbnail(partition_file, thumbnail_file):
|
||||
"""
|
||||
Generates thumbnail if non-existent
|
||||
"""
|
||||
if not os.path.exists(partition_file):
|
||||
abort(404)
|
||||
|
||||
if not os.path.exists(thumbnail_file):
|
||||
generate_thumbnail(partition_file, thumbnail_file)
|
||||
|
||||
return send_file(thumbnail_file)
|
||||
|
||||
|
||||
@bp.route("/search/<uuid>.jpg")
|
||||
@login_required
|
||||
def search_thumbnail(uuid):
|
||||
"""
|
||||
Renvoie l'apercu d'un résultat de recherche
|
||||
"""
|
||||
return serve_thumbnail(
|
||||
os.path.join(current_app.instance_path, "search-partitions", f"{uuid}.pdf"),
|
||||
os.path.join(current_app.instance_path, "cache", "search-thumbnails", f"{uuid}.jpg")
|
||||
)
|
||||
|
||||
@bp.route("/<uuid>.jpg")
|
||||
def regular_thumbnail(uuid):
|
||||
"""
|
||||
Renvoie l'apercu d'une partition déjà enregistrée
|
||||
"""
|
||||
return serve_thumbnail(
|
||||
os.path.join(current_app.instance_path, "partitions", f"{uuid}.pdf"),
|
||||
os.path.join(current_app.instance_path, "cache", "thumbnails", f"{uuid}.jpg")
|
||||
)
|
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 210 KiB |
@ -1,5 +1,5 @@
|
||||
{
|
||||
"background_color": "#eff1f5",
|
||||
"background_color": "#1E1E2E",
|
||||
"description": "Partitioncloud",
|
||||
"display": "fullscreen",
|
||||
"icons": [
|
||||
|
@ -356,6 +356,11 @@ img.partition-thumbnail {
|
||||
transform: translateX(-22px) translateY(-115px);
|
||||
}
|
||||
|
||||
.partition-name {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
/** Albums grid in groupe view */
|
||||
#albums-grid > a > .album {
|
||||
@ -755,6 +760,9 @@ midi-player {
|
||||
margin: 20px;
|
||||
margin-top: 50px;
|
||||
border-radius: 15px;
|
||||
width: 370px;
|
||||
height: 370px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#share-url {
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div>
|
||||
<a href="/partition/{{ partition['uuid'] }}">
|
||||
<div class="partition" id="partition-{{ partition['uuid'] }}">
|
||||
<img class="partition-thumbnail" src="/static/thumbnails/{{ partition['uuid'] }}.jpg">
|
||||
<img class="partition-thumbnail" src="/thumbnails/{{ partition['uuid'] }}.jpg" loading="lazy">
|
||||
<div class="partition-description">
|
||||
<div class="partition-name">{{ partition["name"] }}</div>
|
||||
<div class="partition-author">{{ partition["author"] }}</div>
|
||||
|
@ -78,7 +78,7 @@
|
||||
<div>
|
||||
<a href="/partition/{{ partition['uuid'] }}">
|
||||
<div class="partition" id="partition-{{ partition['uuid'] }}">
|
||||
<img class="partition-thumbnail" src="/static/thumbnails/{{ partition['uuid'] }}.jpg">
|
||||
<img class="partition-thumbnail" src="/thumbnails/{{ partition['uuid'] }}.jpg" loading="lazy">
|
||||
<div class="partition-description">
|
||||
<div class="partition-name">{{ partition["name"] }}</div>
|
||||
<div class="partition-author">{{ partition["author"] }}</div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<div class="partition-container">
|
||||
<a href="/partition/{{ partition['uuid'] }}">
|
||||
<div class="partition" id="partition-{{ partition['uuid'] }}">
|
||||
<img class="partition-thumbnail" src="/static/thumbnails/{{ partition['uuid'] }}.jpg">
|
||||
<img class="partition-thumbnail" src="/thumbnails/{{ partition['uuid'] }}.jpg" loading="lazy">
|
||||
<div class="partition-description">
|
||||
<div class="partition-name">{{ partition["name"] }}</div>
|
||||
<div class="partition-author">{{ partition["author"] }}</div>
|
||||
@ -48,7 +48,7 @@
|
||||
<div class="partition-container">
|
||||
<a href="/partition/search/{{ partition['uuid'] }}">
|
||||
<div class="partition" id="partition-{{ partition['uuid'] }}">
|
||||
<img class="partition-thumbnail" src="/static/search-thumbnails/{{ partition['uuid'] }}.jpg">
|
||||
<img class="partition-thumbnail" src="/thumbnails/search/{{ partition['uuid'] }}.jpg" loading="lazy">
|
||||
<div class="partition-description">
|
||||
<div class="partition-name">{{ partition["name"] }}</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<dialog id="share">
|
||||
<center>
|
||||
<img src="{{ share_qrlink }}" id="share-qrcode"><br/>
|
||||
<img src="{{ share_qrlink }}" id="share-qrcode" loading="lazy"><br/>
|
||||
<div id="share-url" onclick='navigator.clipboard.writeText("{{ share_link }}")'>
|
||||
{{ share_link }}
|
||||
</div>
|
||||
|
@ -50,7 +50,9 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fichier</td>
|
||||
<td><a href="/partition/{{ partition.uuid }}"><img class="partition-thumbnail" src="/static/thumbnails/{{ partition.uuid }}.jpg"></a></td>
|
||||
<td><a href="/partition/{{ partition.uuid }}">
|
||||
<img class="partition-thumbnail" src="/thumbnails/{{ partition.uuid }}.jpg" loading="lazy">
|
||||
</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Titre</td>
|
||||
|
@ -11,7 +11,9 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Fichier</td>
|
||||
<td><a href="/partition/{{ partition.uuid }}"><img class="partition-thumbnail" src="/static/thumbnails/{{ partition.uuid }}.jpg"></a></td>
|
||||
<td><a href="/partition/{{ partition.uuid }}">
|
||||
<img class="partition-thumbnail" src="/thumbnails/{{ partition.uuid }}.jpg" loading="lazy">
|
||||
</a></td>
|
||||
</tr>
|
||||
{% if partition.source != "unknown" and partition.source != "upload" %}
|
||||
<tr>
|
||||
|
5
scripts/hooks/config.py
Normal file
5
scripts/hooks/config.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""
|
||||
Config parameters, shared between files
|
||||
"""
|
||||
|
||||
instance = "instance"
|
@ -1,11 +1,17 @@
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
import sqlite3
|
||||
|
||||
from . import config
|
||||
|
||||
|
||||
def run_sqlite_command(*args):
|
||||
"""Run a command against the database"""
|
||||
con = sqlite3.connect("instance/partitioncloud.sqlite")
|
||||
con = sqlite3.connect(os.path.join(
|
||||
config.instance,
|
||||
"partitioncloud.sqlite"
|
||||
))
|
||||
cur = con.cursor()
|
||||
cur.execute(*args)
|
||||
con.commit()
|
||||
@ -14,7 +20,10 @@ def run_sqlite_command(*args):
|
||||
|
||||
def get_sqlite_data(*args):
|
||||
"""Get data from the db"""
|
||||
con = sqlite3.connect("instance/partitioncloud.sqlite")
|
||||
con = sqlite3.connect(os.path.join(
|
||||
config.instance,
|
||||
"partitioncloud.sqlite"
|
||||
))
|
||||
cur = con.cursor()
|
||||
data = cur.execute(*args)
|
||||
new_data = list(data)
|
||||
|
@ -1,9 +1,11 @@
|
||||
import os
|
||||
import shutil
|
||||
import sqlite3
|
||||
from hooks import utils
|
||||
from colorama import Fore, Style
|
||||
|
||||
from . import utils
|
||||
from . import config
|
||||
|
||||
"""
|
||||
v1.3.*
|
||||
"""
|
||||
@ -159,5 +161,13 @@ def move_instance():
|
||||
for path in paths:
|
||||
shutil.move(
|
||||
os.path.join("partitioncloud", path),
|
||||
os.path.join("instance", path)
|
||||
)
|
||||
os.path.join(config.instance, path)
|
||||
)
|
||||
|
||||
|
||||
def move_thumbnails():
|
||||
shutil.rmtree("partitioncloud/static/thumbnails", ignore_errors=True)
|
||||
shutil.rmtree("partitioncloud/static/search-thumbnails", ignore_errors=True)
|
||||
|
||||
os.makedirs(os.path.join(config.instance, "cache", "thumbnails"), exist_ok=True)
|
||||
os.makedirs(os.path.join(config.instance, "cache", "search-thumbnails"), exist_ok=True)
|
||||
|
@ -6,7 +6,7 @@ import argparse
|
||||
from functools import cmp_to_key
|
||||
|
||||
from colorama import Fore, Style
|
||||
from hooks import v1 as v1_hooks
|
||||
from hooks import v1 as v1_hooks, config
|
||||
|
||||
|
||||
def get_version(v: str) -> (int, int, int):
|
||||
@ -33,7 +33,8 @@ hooks = [
|
||||
],
|
||||
),
|
||||
("v1.4.1", [("Install qrcode", v1_hooks.install_qrcode)]),
|
||||
("v1.5.0", [("Move to instance directory", v1_hooks.move_instance)])
|
||||
("v1.5.0", [("Move to instance directory", v1_hooks.move_instance)]),
|
||||
("v1.5.1", [("Move thumbnails", v1_hooks.move_thumbnails)])
|
||||
]
|
||||
|
||||
|
||||
@ -73,7 +74,7 @@ def backup_instance(version, verbose=True):
|
||||
|
||||
os.makedirs(dest)
|
||||
paths = [
|
||||
("instance", os.path.join(dest, "instance")),
|
||||
(config.instance, os.path.join(dest, "instance")),
|
||||
(
|
||||
os.path.join("partitioncloud", "partitions"),
|
||||
os.path.join(dest, "partitions"),
|
||||
@ -155,7 +156,7 @@ def restore(version):
|
||||
dest = os.path.join("backups", version)
|
||||
print(f"Restoring from {dest}")
|
||||
paths = [
|
||||
("instance", os.path.join(dest, "instance")),
|
||||
(config.instance, os.path.join(dest, "instance")),
|
||||
(
|
||||
os.path.join("partitioncloud", "partitions"),
|
||||
os.path.join(dest, "partitions"),
|
||||
@ -191,6 +192,7 @@ if __name__ == "__main__":
|
||||
|
||||
parser.add_argument("-c", "--current", help="current version (vx.y.z)")
|
||||
parser.add_argument("-t", "--target", help="target version (vx.y.z)")
|
||||
parser.add_argument("-i", "--instance", help="instance folder", default="instance")
|
||||
parser.add_argument("-s", "--skip-backup", action="store_true")
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
@ -199,6 +201,7 @@ if __name__ == "__main__":
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
config.instance = os.path.abspath(args.instance)
|
||||
|
||||
if args.restore is None:
|
||||
migrate(args.current, args.target, skip_backup=args.skip_backup)
|
||||
|
Loading…
Reference in New Issue
Block a user