[trails] Fix webdav importer
All checks were successful
build & deploy / test (push) Successful in 1m54s
build & deploy / build-and-deploy (push) Successful in 26s

This commit is contained in:
2026-05-21 13:54:28 -04:00
parent 7c33095d87
commit 62c200ab05
4 changed files with 40 additions and 12 deletions

View File

@ -129,6 +129,12 @@ class TestImportTrailGPX:
scrobble = Scrobble.objects.filter(source="GPX Import").first() scrobble = Scrobble.objects.filter(source="GPX Import").first()
assert scrobble.playback_position_seconds == pytest.approx(3770, abs=5) assert scrobble.playback_position_seconds == pytest.approx(3770, abs=5)
def test_scrobble_has_timezone(self, user, sample_gpx_path):
import_trail_gpx(sample_gpx_path, user.id)
scrobble = Scrobble.objects.filter(source="GPX Import").first()
assert scrobble.timezone is not None
assert isinstance(scrobble.timezone, str)
def test_scrobble_log_extra_metadata(self, user, sample_gpx_path): def test_scrobble_log_extra_metadata(self, user, sample_gpx_path):
import_trail_gpx(sample_gpx_path, user.id) import_trail_gpx(sample_gpx_path, user.id)
scrobble = Scrobble.objects.filter(source="GPX Import").first() scrobble = Scrobble.objects.filter(source="GPX Import").first()

View File

@ -6,6 +6,7 @@ from datetime import timezone as dt_timezone
from math import asin, cos, radians, sin, sqrt from math import asin, cos, radians, sin, sqrt
from typing import Optional from typing import Optional
from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.files import File from django.core.files import File
@ -268,6 +269,7 @@ def import_trail_gpx(file_path, user_id, original_filename=None):
source="GPX Import", source="GPX Import",
trail=trail, trail=trail,
log=logdata.asdict, log=logdata.asdict,
timezone=user.profile.timezone or settings.TIME_ZONE,
played_to_completion=True, played_to_completion=True,
in_progress=False, in_progress=False,
media_type=Scrobble.MediaType.TRAIL, media_type=Scrobble.MediaType.TRAIL,

View File

@ -11,10 +11,16 @@ from webdav.client import get_webdav_client
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
DEFAULT_GPX_PATH = "var/gpx/"
DEFAULT_KOREADER_PATH = "var/koreader/"
def import_from_webdav_for_all_users(restart=False): def import_from_webdav_for_all_users(restart=False):
"""Grab a list of all users with WebDAV enabled and kickoff imports for them""" """Grab a list of all users with WebDAV enabled and kickoff imports for them"""
koreader_path = (
DEFAULT_KOREADER_PATH + "statistics.sqlite3"
) # TODO Allow configuring this in user settings
webdav_enabled_user_ids = UserProfile.objects.filter( webdav_enabled_user_ids = UserProfile.objects.filter(
webdav_url__isnull=False, webdav_url__isnull=False,
webdav_user__isnull=False, webdav_user__isnull=False,
@ -30,7 +36,7 @@ def import_from_webdav_for_all_users(restart=False):
webdav_client = get_webdav_client(user_id) webdav_client = get_webdav_client(user_id)
try: try:
webdav_client.info("var/koreader/statistics.sqlite3") webdav_client.info(koreader_path)
koreader_found = True koreader_found = True
except: except:
koreader_found = False koreader_found = False
@ -39,6 +45,8 @@ def import_from_webdav_for_all_users(restart=False):
extra={"user_id": user_id}, extra={"user_id": user_id},
) )
trail_gpx_import_count += scan_webdav_for_gpx(webdav_client, user_id)
if koreader_found: if koreader_found:
last_import = ( last_import = (
KoReaderImport.objects.filter( KoReaderImport.objects.filter(
@ -48,8 +56,7 @@ def import_from_webdav_for_all_users(restart=False):
.last() .last()
) )
koreader_file_path = fetch_file_from_webdav(1) new_hash = get_file_md5_hash(fetch_file_from_webdav(1))
new_hash = get_file_md5_hash(koreader_file_path)
old_hash = None old_hash = None
if last_import: if last_import:
old_hash = last_import.file_md5_hash() old_hash = last_import.file_md5_hash()
@ -81,29 +88,31 @@ def import_from_webdav_for_all_users(restart=False):
process_koreader_import.delay(koreader_import.id) process_koreader_import.delay(koreader_import.id)
koreader_import_count += 1 koreader_import_count += 1
trail_gpx_import_count += scan_webdav_for_gpx(webdav_client, user_id)
return koreader_import_count, trail_gpx_import_count return koreader_import_count, trail_gpx_import_count
def scan_webdav_for_gpx(webdav_client, user_id): def scan_webdav_for_gpx(webdav_client, user_id):
gpx_path = DEFAULT_GPX_PATH # TODO allow this to be configured in user settings
try: try:
webdav_client.info("gpx/") webdav_client.info(DEFAULT_GPX_PATH)
except: except:
logger.info("No gpx/ directory on webdav", extra={"user_id": user_id}) logger.info("No var/gpx/ directory on webdav", extra={"user_id": user_id})
return 0 return 0
try: try:
files = webdav_client.list("gpx/") files = webdav_client.list(gpx_path)
except Exception as e: except Exception as e:
logger.warning("Could not list gpx/", extra={"user_id": user_id, "error": str(e)}) logger.warning(
"Could not list var/gpx/", extra={"user_id": user_id, "error": str(e)}
)
return 0 return 0
gpx_extensions = (".gpx", ".fit") gpx_extensions = (".gpx", ".fit")
new_imports = 0 new_imports = 0
already_imported = set( already_imported = set(
TrailGPXImport.objects.filter(user_id=user_id) TrailGPXImport.objects.filter(user_id=user_id).values_list(
.values_list("original_filename", flat=True) "original_filename", flat=True
)
) )
for fname in files: for fname in files:
@ -116,7 +125,9 @@ def scan_webdav_for_gpx(webdav_client, user_id):
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=fname) tmp = tempfile.NamedTemporaryFile(delete=False, suffix=fname)
try: try:
webdav_client.download_sync(remote_path=f"gpx/{fname}", local_path=tmp.name) webdav_client.download_sync(
remote_path=f"{gpx_path}/{fname}", local_path=tmp.name
)
imp = TrailGPXImport.objects.create( imp = TrailGPXImport.objects.create(
user_id=user_id, user_id=user_id,
original_filename=fname, original_filename=fname,

View File

@ -72,6 +72,15 @@
<p>No moods felt today </p> <p>No moods felt today </p>
{% endif %} {% endif %}
<h3><a href="{% url 'trails:trail_list' %}">Trails</a></h3>
{% if Trail %}
{% with scrobbles=Trail count=Trail_count time=Trail_time %}
{% include "scrobbles/_scrobble_table.html" %}
{% endwith %}
{% else %}
<p>No trails hiked today</p>
{% endif %}
</div> </div>
<div class="col-md"> <div class="col-md">