Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 45 additions & 35 deletions locale/themerr.po
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,23 @@ msgid ""
"Servers page."
msgstr ""

#: src/common/config.py:260 src/common/config.py:361
#: src/common/config.py:260 src/common/config.py:368
msgid "Movie support"
msgstr ""

#: src/common/config.py:261
msgid "Add themes to Jellyfin movies."
msgstr ""

#: src/common/config.py:264 src/common/config.py:367
#: src/common/config.py:264 src/common/config.py:374
msgid "Series support"
msgstr ""

#: src/common/config.py:265
msgid "Add themes to Jellyfin series."
msgstr ""

#: src/common/config.py:268 src/common/config.py:355 web/templates/home.html:31
#: src/common/config.py:268 src/common/config.py:362 web/templates/home.html:31
msgid "Collections"
msgstr ""

Expand Down Expand Up @@ -359,144 +359,154 @@ msgid "Themerr settings."
msgstr ""

#: src/common/config.py:349
msgid "Themerr Enabled"
msgid "Scan on startup"
msgstr ""

#: src/common/config.py:350
msgid "When enabled, Themerr will attempt to update themes."
msgid ""
"Run the theme scan when Themerr starts. Scheduled scans still run when "
"this is disabled. Changes apply the next time Themerr starts."
msgstr ""

#: src/common/config.py:356
msgid "Themerr Enabled"
msgstr ""

#: src/common/config.py:357
msgid "When enabled, Themerr will attempt to update themes."
msgstr ""

#: src/common/config.py:363
msgid "Add themes to collections."
msgstr ""

#: src/common/config.py:362
#: src/common/config.py:369
msgid "Add themes to movies using the Plex Movie agent."
msgstr ""

#: src/common/config.py:368
#: src/common/config.py:375
msgid "Add themes to series using the Plex Series agent."
msgstr ""

#: src/common/config.py:373
#: src/common/config.py:380
msgid "Overwrite Plex themes"
msgstr ""

#: src/common/config.py:374
#: src/common/config.py:381
msgid "When enabled, Themerr will overwrite themes provided by Plex."
msgstr ""

#: src/common/config.py:379
#: src/common/config.py:386
msgid "Prefer MP4A AAC Codec"
msgstr ""

#: src/common/config.py:380
#: src/common/config.py:387
msgid "This can improve theme compatibility with Apple devices."
msgstr ""

#: src/common/config.py:385
#: src/common/config.py:392
msgid "Remove unused themes"
msgstr ""

#: src/common/config.py:386
#: src/common/config.py:393
msgid ""
"Frees up space in your Plex metadata directory. This option requires that"
" the \"Plex data directory\" path is set"
msgstr ""

#: src/common/config.py:392
#: src/common/config.py:399
msgid "Remove unused art"
msgstr ""

#: src/common/config.py:393 src/common/config.py:401
#: src/common/config.py:400 src/common/config.py:408
msgid ""
"Applies to collection. Frees up space in your Plex metadata directory. "
"This option requires that the \"Plex data directory\" path is set"
msgstr ""

#: src/common/config.py:400
#: src/common/config.py:407
msgid "Remove unused posters"
msgstr ""

#: src/common/config.py:408
#: src/common/config.py:415
msgid "Collection metadata"
msgstr ""

#: src/common/config.py:409
#: src/common/config.py:416
msgid ""
"Update collection metadata (poster, art, and summary) during scheduled "
"update."
msgstr ""

#: src/common/config.py:414
#: src/common/config.py:421
msgid "Ignore locked fields."
msgstr ""

#: src/common/config.py:415
#: src/common/config.py:422
msgid ""
"If you used Themerr v2024.813.13709 or lower, you may need to enable this"
" to update items."
msgstr ""

#: src/common/config.py:421
#: src/common/config.py:428
msgid "Ignored library IDs"
msgstr ""

#: src/common/config.py:422
#: src/common/config.py:429
msgid ""
"Comma-separated library IDs to exclude from scheduled updates. IDs appear"
" on Home."
msgstr ""

#: src/common/config.py:428
#: src/common/config.py:435
msgid "Update themes interval"
msgstr ""

#: src/common/config.py:429
#: src/common/config.py:436
msgid "Interval for automatic update task, in minutes (min: 15)."
msgstr ""

#: src/common/config.py:436
#: src/common/config.py:443
msgid "Update database cache interval"
msgstr ""

#: src/common/config.py:437
#: src/common/config.py:444
msgid "Interval for database cache update task, in minutes (min: 15)."
msgstr ""

#: src/common/config.py:444
#: src/common/config.py:451
msgid "PlexAPI timeout"
msgstr ""

#: src/common/config.py:445
#: src/common/config.py:452
msgid ""
"Increase this slightly if you experience timeouts when adding themes. "
"(min: 1)"
msgstr ""

#: src/common/config.py:452
#: src/common/config.py:459
msgid "Theme upload retries"
msgstr ""

#: src/common/config.py:453
#: src/common/config.py:460
msgid "If uploading themes fail, retry this many times. (min: 0)"
msgstr ""

#: src/common/config.py:460
#: src/common/config.py:467
msgid "Multiprocessing thread count"
msgstr ""

#: src/common/config.py:461
#: src/common/config.py:468
msgid ""
"The number of threads to use when adding themes. Restart required. (min: "
"1)"
msgstr ""

#: src/common/config.py:469
#: src/common/config.py:476
msgid "YouTube Cookies"
msgstr ""

#: src/common/config.py:471
#: src/common/config.py:478
msgid ""
"Optional: export youtube.com cookies with Get cookies.txt LOCALLY using "
"its JSON format, then paste the entire JSON array here and save. Saved "
Expand All @@ -505,7 +515,7 @@ msgid ""
"them."
msgstr ""

#: src/common/config.py:478
#: src/common/config.py:485
msgid "Cookie export instructions"
msgstr ""

Expand Down
7 changes: 7 additions & 0 deletions src/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ def on_change_plex_url() -> None:
'name': _('Themerr'),
'description': _('Themerr settings.'),
'icon': 'music',
'BOOL_SCAN_ON_BOOT': {
'type': 'boolean',
'name': _('Scan on startup'),
'description': _('Run the theme scan when Themerr starts. Scheduled scans still run when this is '
'disabled. Changes apply the next time Themerr starts.'),
'default': True,
},
'BOOL_THEMERR_ENABLED': {
'type': 'boolean',
'name': _('Themerr Enabled'),
Expand Down
12 changes: 10 additions & 2 deletions src/themerr/scheduled_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
_job_lock = threading.RLock()
_jobs = deque(maxlen=30)
_running = {}
_SCAN_TAG = 'theme-scan'


def run_threaded(
Expand Down Expand Up @@ -108,7 +109,14 @@ def schedule_loop() -> None:
...
"""
log.info('Scheduler started; dispatching initial jobs')
schedule.run_all() # run all jobs once
if config.CONFIG['Themerr']['BOOL_SCAN_ON_BOOT']:
schedule.run_all() # run all jobs once
else:
log.info('Skipping the startup theme scan because Scan on startup is disabled')
skipped = schedule.get_jobs(_SCAN_TAG)
for job in schedule.jobs[:]:
if job not in skipped:
job.run()

while True:
schedule.run_pending()
Expand All @@ -124,7 +132,7 @@ def configure_jobs() -> None:
target=scheduled_update,
daemon=True,
task_name='Theme scan and queue',
).tag('themerr')
).tag('themerr', _SCAN_TAG)

schedule.every(max(15, int(config.CONFIG['Themerr']['INT_UPDATE_DATABASE_CACHE_INTERVAL']))).minutes.do(
job_func=run_threaded,
Expand Down
42 changes: 41 additions & 1 deletion tests/unit/themerr/test_scheduled_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from threading import Event
from unittest.mock import Mock

# lib imports
import pytest

# local imports
from themerr import scheduled_tasks

Expand Down Expand Up @@ -39,7 +42,7 @@ def test_scheduled_task_failure_is_logged_and_thread_exits(monkeypatch):
assert error.call_args.args[:2] == ('Scheduled task failed: %s (%.1f seconds)', 'Theme scan and queue')


def test_schedule_loop(monkeypatch):
def test_schedule_loop(configured, monkeypatch):
run_all = Mock()
pending = Mock()

Expand Down Expand Up @@ -127,3 +130,40 @@ def test_reconfigure_changes_intervals_without_duplicating_or_removing_other_job
assert scheduler.get_jobs('other') == [unrelated]
finally:
scheduler.clear()


def test_scan_on_boot_defaults_to_enabled(configured):
assert configured['Themerr']['BOOL_SCAN_ON_BOOT'] is True


def test_disabled_scan_on_boot_survives_a_config_reload(configured):
from common import config
configured['Themerr']['BOOL_SCAN_ON_BOOT'] = False
assert config.save_config(configured)
reloaded = config.create_config(configured.filename)
assert reloaded['Themerr']['BOOL_SCAN_ON_BOOT'] is False


def test_schedule_loop_skips_only_the_startup_scan_when_disabled(configured, monkeypatch):
scheduler = scheduled_tasks.schedule
scheduler.clear()
dispatched = []
monkeypatch.setattr(scheduled_tasks, 'run_threaded', lambda **kwargs: dispatched.append(kwargs['task_name']))

def stop(seconds):
raise RuntimeError('stop')

monkeypatch.setattr(scheduled_tasks.time, 'sleep', stop)
try:
configured['Themerr']['BOOL_THEMERR_ENABLED'] = True
configured['Themerr']['BOOL_SCAN_ON_BOOT'] = False
scheduled_tasks.configure_jobs()
with pytest.raises(RuntimeError):
scheduled_tasks.schedule_loop()
assert 'Theme scan and queue' not in dispatched
assert 'Dashboard refresh' in dispatched
scan_jobs = scheduler.get_jobs('theme-scan')
assert len(scan_jobs) == 1
assert scan_jobs[0].next_run is not None
finally:
scheduler.clear()
Loading