From 7c2f65bbf43719132f092d44bbcb2806a97a5ccf Mon Sep 17 00:00:00 2001 From: "peter.fong" Date: Mon, 15 Dec 2025 23:59:01 +0100 Subject: [PATCH] add m4btool worker, statuscheck and audio completion flow - Add dedicated m4b Docker image and mp4v2 tooling - Introduce statuscheck task for filesystem-based validation - Add audio completion service and m4b task pipeline - Align repository counters with audio/m4b workflow - Clean up legacy project.zip artifact --- bookscraper/README.md | 13 +- bookscraper/db/repository.py | 326 +++++++----------- bookscraper/docker-compose.yml | 19 + bookscraper/docker/Dockerfile.m4b | 70 ++++ bookscraper/mp4v2 | 1 + bookscraper/project.zip | Bin 89157 -> 0 bytes .../scraper/services/audio_completion.py | 94 +++++ bookscraper/scraper/tasks/audio_tasks.py | 4 + bookscraper/scraper/tasks/m4b_tasks.py | 132 +++++++ bookscraper/scraper/tasks/statuscheck.py | 149 ++++++++ bookscraper/tools/mp4info | 13 + 11 files changed, 622 insertions(+), 199 deletions(-) create mode 100644 bookscraper/docker/Dockerfile.m4b create mode 160000 bookscraper/mp4v2 delete mode 100644 bookscraper/project.zip create mode 100644 bookscraper/scraper/services/audio_completion.py create mode 100644 bookscraper/scraper/tasks/m4b_tasks.py create mode 100644 bookscraper/scraper/tasks/statuscheck.py create mode 100644 bookscraper/tools/mp4info diff --git a/bookscraper/README.md b/bookscraper/README.md index e53e997..9fdb189 100644 --- a/bookscraper/README.md +++ b/bookscraper/README.md @@ -125,7 +125,8 @@ docker run \ ``` -docker compose down +docker compose down --remove-orphans +docker image prune -f docker builder prune -af docker volume prune -f docker compose build --no-cache @@ -141,6 +142,10 @@ docker compose build --no-cache web && docker compose up web docker compose build worker_download && docker compose up worker_download +docker compose down --remove-orphans +docker compose build --no-cache worker_m4b +docker compose up -d worker_m4b + docker compose up web docker compose build web docker compose restart web @@ -152,3 +157,9 @@ tar \ --exclude=".venv" \ --exclude="venv" \ -czvf project.tar.gz . + +docker compose down +docker image rm bookscraper-worker_m4b || true +docker builder prune -af +docker compose build --no-cache worker_m4b +docker compose up -d worker_m4b diff --git a/bookscraper/db/repository.py b/bookscraper/db/repository.py index b58b7bb..83e6f77 100644 --- a/bookscraper/db/repository.py +++ b/bookscraper/db/repository.py @@ -9,7 +9,7 @@ # - Provide a clean API for tasks and Flask UI # ============================================================ # ============================================================ -# File: db/repository.py (UPDATED for book_idx-only architecture) +# UPDATED — canonical read model via get_book_state # ============================================================ from scraper.logger_decorators import logcall @@ -17,7 +17,6 @@ from logbus.publisher import log import redis import os -import time # ============================================================ # SQL low-level engines (snapshot storage) @@ -29,10 +28,6 @@ from db.state_sql import ( sql_set_chapters_total, sql_register_book, sql_update_book, - sql_inc_downloaded, - sql_inc_parsed, - sql_inc_audio_done, - sql_inc_audio_skipped, ) # ============================================================ @@ -49,80 +44,34 @@ from db.state_redis import ( ) # ============================================================ -# Redis setup for legacy progress paths +# Redis client (read-only for legacy + guards) # ============================================================ REDIS_URL = os.getenv("REDIS_BROKER", "redis://redis:6379/0") _r = redis.Redis.from_url(REDIS_URL, decode_responses=True) # ============================================================ -# INTERNAL — LEGACY PROGRESS HELPERS (kept for UI) -# Keys remain: progress:{book_idx}:* +# LEGACY PROGRESS (UI only, unchanged) # ============================================================ -def _legacy_set_total(book_idx, total): - _r.set(f"progress:{book_idx}:total", total) - - -def _legacy_inc_completed(book_idx): - _r.incr(f"progress:{book_idx}:completed") - - -def _legacy_inc_skipped(book_idx): - _r.incr(f"progress:{book_idx}:skipped") - - -def _legacy_inc_failed(book_idx): - _r.incr(f"progress:{book_idx}:failed") - - -def _legacy_add_failed_chapter(book_idx, chapter, reason): - entry = f"Chapter {chapter}: {reason}" - _r.rpush(f"progress:{book_idx}:failed_list", entry) - - -def _legacy_get_failed_list(book_idx): - return _r.lrange(f"progress:{book_idx}:failed_list", 0, -1) - - def _legacy_get_progress(book_idx): - total = int(_r.get(f"progress:{book_idx}:total") or 0) - completed = int(_r.get(f"progress:{book_idx}:completed") or 0) - skipped = int(_r.get(f"progress:{book_idx}:skipped") or 0) - failed = int(_r.get(f"progress:{book_idx}:failed") or 0) - abort = _r.exists(f"abort:{book_idx}") == 1 - failed_list = _legacy_get_failed_list(book_idx) - return { "book_idx": book_idx, - "total": total, - "completed": completed, - "skipped": skipped, - "failed": failed, - "failed_list": failed_list, - "abort": abort, + "total": int(_r.get(f"progress:{book_idx}:total") or 0), + "completed": int(_r.get(f"progress:{book_idx}:completed") or 0), + "skipped": int(_r.get(f"progress:{book_idx}:skipped") or 0), + "failed": int(_r.get(f"progress:{book_idx}:failed") or 0), + "abort": _r.exists(f"abort:{book_idx}") == 1, + "failed_list": _r.lrange(f"progress:{book_idx}:failed_list", 0, -1), } -# ============================================================ -# PUBLIC — PROGRESS API -# ============================================================ @logcall def get_progress(book_idx): return _legacy_get_progress(book_idx) -@logcall -def add_failed_chapter(book_idx, chapter, reason): - _legacy_add_failed_chapter(book_idx, chapter, reason) - - -@logcall -def get_failed_list(book_idx): - return _legacy_get_failed_list(book_idx) - - # ============================================================ -# FETCH OPERATIONS (SQLite snapshot) +# FETCH (SQLite snapshot) # ============================================================ @logcall def fetch_book(book_idx): @@ -135,7 +84,7 @@ def fetch_all_books(): # ============================================================ -# INIT-FLOW (SQLite metadata only) +# INIT / UPDATE METADATA # ============================================================ @logcall def register_book( @@ -147,26 +96,22 @@ def register_book( cover_path=None, book_url=None, ): - - fields = { - "book_idx": book_idx, - "title": title, - "author": author, - "description": description, - "cover_url": cover_url, - "cover_path": cover_path, - "book_url": book_url, - "chapters_total": 0, - "status": "registered", - } - - log(f"[DB] Registering new book_idx={book_idx} title='{title}'") - sql_register_book(book_idx, fields) + sql_register_book( + book_idx, + { + "book_idx": book_idx, + "title": title, + "author": author, + "description": description, + "cover_url": cover_url, + "cover_path": cover_path, + "book_url": book_url, + "chapters_total": 0, + "status": "registered", + }, + ) -# ============================================================ -# SCRAPE-FLOW UPDATE -# ============================================================ @logcall def update_book_after_full_scrape( book_idx, @@ -176,9 +121,7 @@ def update_book_after_full_scrape( cover_url=None, chapters_total=None, ): - fields = {} - if title is not None: fields["title"] = title if author is not None: @@ -191,143 +134,72 @@ def update_book_after_full_scrape( fields["chapters_total"] = chapters_total fields["status"] = "active" - - log(f"[DB] update metadata for book_idx={book_idx}") sql_update_book(book_idx, fields) # ============================================================ -# ACTIVE BOOK LISTS -# ============================================================ -@logcall -def get_registered_books(): - all_books = sql_fetch_all_books() - HIDDEN_STATES = {"hidden"} - log(f"[DB] Fetched all books for registered filter, total={len(all_books)}") - return [b for b in all_books if b.get("status") not in HIDDEN_STATES] - - -@logcall -def get_active_books(): - all_books = sql_fetch_all_books() - - HIDDEN_STATES = {"hidden", "done"} - log(f"[DB] Fetched all books for active filter, total={len(all_books)}") - return [b for b in all_books if b.get("status") not in HIDDEN_STATES] - - -# ============================================================ -# STATUS MANAGEMENT +# STATUS # ============================================================ @logcall def set_status(book_idx, status): - log(f"[DB] Setting status for {book_idx} to '{status}'") redis_set_status(book_idx, status) sql_set_status(book_idx, status) # ============================================================ -# CHAPTER TOTALS +# TOTALS # ============================================================ @logcall def set_chapters_total(book_idx, total): - log(f"[DB] Setting chapter total for {book_idx} to {total}") redis_set_chapters_total(book_idx, total) sql_set_chapters_total(book_idx, total) - # _legacy_set_total(book_idx, total) # ============================================================ -# COUNTERS — DOWNLOAD +# COUNTERS — WRITE ONLY # ============================================================ @logcall def inc_download_done(book_idx, amount=1): - log(f"[DB] Incrementing download done for {book_idx} by {amount}") redis_inc_download_done(book_idx, amount) - # sql_inc_downloaded(book_idx, amount) - # _legacy_inc_completed(book_idx) @logcall def inc_download_skipped(book_idx, amount=1): - log(f"[DB] Incrementing download skipped for {book_idx} by {amount}") redis_inc_download_skipped(book_idx, amount) - # _legacy_inc_skipped(book_idx) -# ============================================================ -# COUNTERS — PARSE -# ============================================================ @logcall def inc_parsed_done(book_idx, amount=1): - log(f"[DB] Incrementing parsed done for {book_idx} by {amount}") redis_inc_parsed_done(book_idx, amount) - # sql_inc_parsed(book_idx, amount) - - -# ============================================================ -# COUNTERS — AUDIO -# ============================================================ -@logcall -def inc_audio_skipped(book_idx, amount=1): - log(f"[DB] Incrementing audio skipped for {book_idx} by {amount}") - # sql_inc_audio_skipped(book_idx, amount) - redis_inc_audio_skipped(book_idx, amount) @logcall def inc_audio_done(book_idx, amount=1): - log(f"[DB] Incrementing audio done for {book_idx} by {amount}") redis_inc_audio_done(book_idx, amount) - # sql_inc_audio_done(book_idx, amount) -# ============================================================ -# BACKWARDS COMPATIBILITY SHIMS -# These map the old API (book_id) to the new book_idx-only system -# ============================================================ @logcall -def inc_downloaded(book_idx, amount=1): - return inc_download_done(book_idx, amount) - - -@logcall -def inc_parsed(book_idx, amount=1): - return inc_parsed_done(book_idx, amount) - - -@logcall -def inc_audio_done_legacy(book_idx, amount=1): - return inc_audio_done(book_idx, amount) +def inc_audio_skipped(book_idx, amount=1): + redis_inc_audio_skipped(book_idx, amount) # ============================================================ -# READ — DERIVED BOOK STATE +# CANONICAL READ MODEL # ============================================================ @logcall def get_book_state(book_idx): """ - Canonical merged read-model for a single book. + Canonical merged read model. - Gedrag: - - Leest SQL (snapshot) - - Leest Redis (live counters) - - Rekent naar merged - - GEEN writes - - GEEN side-effects - - Merge-regels: + Rules: + - SQL = snapshot baseline + - Redis = live counters - merged = max(sql, redis) - - merged wordt gecapt op chapters_total + - capped at chapters_total """ - # ---------------------------------------------------- - # 1. Fetch bronnen - # ---------------------------------------------------- sqlite_row = sql_fetch_book(book_idx) or {} - - key = f"book:{book_idx}:state" - redis_state = _r.hgetall(key) or {} + redis_state = _r.hgetall(f"book:{book_idx}:state") or {} def _int(v): try: @@ -335,56 +207,114 @@ def get_book_state(book_idx): except Exception: return 0 - # ---------------------------------------------------- - # 2. SQL snapshot - # ---------------------------------------------------- chapters_total = _int(sqlite_row.get("chapters_total")) + + # SQL snapshot sql_downloaded = _int(sqlite_row.get("downloaded")) sql_audio_done = _int(sqlite_row.get("audio_done")) + sql_audio_skipped = _int(sqlite_row.get("audio_skipped")) - # ---------------------------------------------------- - # 3. Redis live counters - # ---------------------------------------------------- + # Redis live redis_downloaded = _int(redis_state.get("chapters_download_done")) + _int( redis_state.get("chapters_download_skipped") ) - redis_audio_done = _int(redis_state.get("audio_done")) + redis_audio_skipped = _int(redis_state.get("audio_skipped")) - # ---------------------------------------------------- - # 4. Merge (SQL vs Redis) - # ---------------------------------------------------- + # Merge merged_downloaded = max(sql_downloaded, redis_downloaded) merged_audio_done = max(sql_audio_done, redis_audio_done) + merged_audio_skipped = max(sql_audio_skipped, redis_audio_skipped) if chapters_total > 0: merged_downloaded = min(merged_downloaded, chapters_total) merged_audio_done = min(merged_audio_done, chapters_total) + merged_audio_skipped = min(merged_audio_skipped, chapters_total) + + audio_completed = merged_audio_done + merged_audio_skipped + + # Build state + state = dict(sqlite_row) + state.update( + { + "downloaded": merged_downloaded, + "audio_done": merged_audio_done, + "audio_skipped": merged_audio_skipped, + "chapters_total": chapters_total, + } + ) - # ---------------------------------------------------- - # 5. Bouw merged state (read-only) - # ---------------------------------------------------- - state = {} - - # Basis = SQL - state.update(sqlite_row) - - # Overschrijf alleen met merged conclusies - state["downloaded"] = merged_downloaded - state["audio_done"] = merged_audio_done - state["chapters_total"] = chapters_total - # ---------------------------------------------------- - # 4b. Derive status (READ-ONLY) - # ---------------------------------------------------- - derived_status = sqlite_row.get("status") or "unknown" - + # Derived status + status = sqlite_row.get("status") or "unknown" if chapters_total > 0: if merged_downloaded < chapters_total: - derived_status = "downloading" - elif merged_downloaded == chapters_total and merged_audio_done < chapters_total: - derived_status = "audio" - elif merged_audio_done == chapters_total: - derived_status = "done" - state["status"] = derived_status + status = "downloading" + elif merged_downloaded == chapters_total and audio_completed < chapters_total: + status = "audio" + elif audio_completed >= chapters_total: + status = "done" + state["status"] = status return state + + +# ============================================================ +# READ HELPERS (VIA get_book_state ONLY) +# ============================================================ +@logcall +def get_chapters_total(book_idx): + return int(get_book_state(book_idx).get("chapters_total", 0)) + + +@logcall +def get_audio_done(book_idx): + return int(get_book_state(book_idx).get("audio_done", 0)) + + +@logcall +def get_audio_completed_total(book_idx): + state = get_book_state(book_idx) + return int(state.get("audio_done", 0)) + int(state.get("audio_skipped", 0)) + + +# ============================================================ +# STATUSCHECK GUARD (INTENTIONAL DIRECT REDIS) +# ============================================================ +@logcall +def try_trigger_statuscheck(book_idx): + return bool(_r.set(f"book:{book_idx}:statuscheck:triggered", "1", nx=True)) + + +# ============================================================ +# ACTIVE / REGISTERED BOOK LISTS (UI API) +# ============================================================ +@logcall +def get_registered_books(): + """ + Books visible in the 'registered' list in the UI. + """ + all_books = sql_fetch_all_books() + HIDDEN_STATES = {"hidden"} + return [b for b in all_books if b.get("status") not in HIDDEN_STATES] + + +@logcall +def get_active_books(): + """ + Books currently active in the dashboard. + """ + all_books = sql_fetch_all_books() + HIDDEN_STATES = {"hidden", "done"} + return [b for b in all_books if b.get("status") not in HIDDEN_STATES] + + +@logcall +def store_m4b_error(book_idx: str, volume: str, error_text: str): + """ + Passive storage of m4b errors. + No logic, no retries, no state transitions. + """ + key = f"book:{book_idx}:m4b:errors" + entry = f"{volume}: {error_text}" + + _r.rpush(key, entry) diff --git a/bookscraper/docker-compose.yml b/bookscraper/docker-compose.yml index 5c6b8c8..c0a4df7 100644 --- a/bookscraper/docker-compose.yml +++ b/bookscraper/docker-compose.yml @@ -149,3 +149,22 @@ services: - .env command: celery -A celery_app worker -Q scraping -n scraping@%h -l INFO restart: "no" + # ---------------------------------------------------------- + # M4B Worker (Finalization) + # ---------------------------------------------------------- + worker_m4b: + build: + context: . + dockerfile: docker/Dockerfile.m4b + container_name: worker_m4b + command: celery -A celery_app worker -Q m4b -n m4b@%h -l INFO + depends_on: + redis: + condition: service_healthy + env_file: + - .env + volumes: + - .:/app + - /Users/peter/mnt/asustor/Sync/bookscraper/books:/Users/peter/mnt/asustor/Sync/bookscraper/books + - /Users/peter/mnt/asustor/Sync/bookscraper/db:/Users/peter/mnt/asustor/Sync/bookscraper/db + restart: "no" diff --git a/bookscraper/docker/Dockerfile.m4b b/bookscraper/docker/Dockerfile.m4b new file mode 100644 index 0000000..b2eecf6 --- /dev/null +++ b/bookscraper/docker/Dockerfile.m4b @@ -0,0 +1,70 @@ +FROM debian:12 + +ENV DEBIAN_FRONTEND=noninteractive + +# ---------------------------------------------------------- +# System + PHP (PHP 8.2 native) +# ---------------------------------------------------------- +RUN apt-get update && apt-get install -y \ + ffmpeg \ + curl \ + ca-certificates \ + bash \ + php-cli \ + php-intl \ + php-json \ + php-mbstring \ + php-xml \ + php-curl \ + php-zip \ + python3 \ + python3-pip \ + python3-venv \ + \ + # build deps for mp4v2 + git \ + build-essential \ + autoconf \ + automake \ + libtool \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# ---------------------------------------------------------- +# Python venv (PEP 668 compliant) +# ---------------------------------------------------------- +RUN python3 -m venv /opt/venv +ENV PATH="/opt/venv/bin:/usr/local/bin:$PATH" + +# ---------------------------------------------------------- +# Build & install mp4v2 (mp4info) +# ---------------------------------------------------------- +WORKDIR /tmp + +RUN git clone https://github.com/sandreas/mp4v2 \ + && cd mp4v2 \ + && ./configure \ + && make -j$(nproc) \ + && make install \ + && echo "/usr/local/lib" > /etc/ld.so.conf.d/mp4v2.conf \ + && ldconfig \ + && cd / \ + && rm -rf /tmp/mp4v2 + +# ---------------------------------------------------------- +# Install m4b-tool +# ---------------------------------------------------------- +RUN curl -L https://github.com/sandreas/m4b-tool/releases/latest/download/m4b-tool.phar \ + -o /usr/local/bin/m4b-tool \ + && chmod +x /usr/local/bin/m4b-tool + +# ---------------------------------------------------------- +# App +# ---------------------------------------------------------- +WORKDIR /app +COPY requirements.txt /app/requirements.txt +RUN pip install --no-cache-dir -r requirements.txt + +COPY . /app + +CMD ["bash"] diff --git a/bookscraper/mp4v2 b/bookscraper/mp4v2 new file mode 160000 index 0000000..480a733 --- /dev/null +++ b/bookscraper/mp4v2 @@ -0,0 +1 @@ +Subproject commit 480a73324f53d0d24bea4931c3902097f8e2a663 diff --git a/bookscraper/project.zip b/bookscraper/project.zip deleted file mode 100644 index 6da01aa6c9783043ade1ae2cf96d8d666445d901..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89157 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

1<<<$@n2wtl%h%Yn?; zhb!^QkWX506*y@Pg|}tO-N*xmmcsLSrb&BT427M8rM?4T*E@czMTp;M(S}o9L5^T> zm$@ zsZ2D^w-UGAb48)wr!uzAKlMA_?-Bi-as50xCt76hmzrNT2m*cO>+{O*!Vu2`i!vE)Lt1jI#QI_2fJLw2W5T4ANc8 zhGrPO1rh0{MP0TfnJ?~qT6NY#o##f;9sQ-`CRW%{+ku{%mo5%k-j9Qw`?Ia@BmmLl zt?vZ!bE8SiLEgmAb#?|@b%-%NT*1b)F+%%?8yr04^X=s@L_4Scd9GuCpzSYk@vg6)xCdo;pnxD2+DXaUpsW34354;q8 z>7+EpP!5RlSG0TEYY$nhYF&t;ZQe>=KOMZeE0r3u$R5%m!lo^>mkp||Kvus8;vu+ zH$19R>ehZ>kFZ~hKCW`Ly0kSi%Dt9`()7Hefm=C$$)~AnLzR;@$pyMZYpZ;$t{uF4 zsQtmo6*v=_@Gl*m7kUTe4k_RzpBdl#74YU(@aQ%F%SKfWrU6#k=7#T zU4c|RYBKEXT`OPcBi zZMitr_}q_`2ZeDDe>eF&Z^J?xsI?OQifk&YU@JuTtvzaeN`k0&nk~nMjn;qiq}6wv zUe(M&Q*QS?tv0gZB z*x+_j&UvS%@Ly&jx?#Zj*GSD#7oQVRaOq#A0A&ny(ojzvj_>`CLowW7{S);dNxD?T zdqsCO0jje8R7}Y%d*rx~$4l={(L%WAeU3}Xm}%M)On-#II)_WU{M)Xl?*eLD8cs31 z!XYF)(aWsih9sJ3xhXVlzdcM5%3dr1{RwYyDU8n0D0?W8()bO$l zh3g>lv$p3(y-S4QCbcES`!J+Abmeh>hRcQrTtEnK<-I}l`z%qMtG32ci|yGQ6!i|M z0k~tSO!Qub!~&0FEAmD!^i!Zch9b$pjen1Z?zaJA}M?-A3fUSb4W-K z{hH0Y0#7M*5n2@t5te)Dh@VL~vC#@rHF$t;U#Eml8;<8%fzv9xlZ1O4s;5W__yM9H?Y5d{qf9mf-lXRyO11MSNT{Yc2`9 z;{7^iM(jv^1gfAMCZvM?5nDRS;C52HSB| zo82+}bhmsYxc;XOL;}ZH!UgM{o1ZCqmz8WFkZfdF?a^q&&z@#cUu924Z;iq^b~AOQ zCAd}(v`+(j5k!y}qJMwWe^g`LiL`aeYI*>z;&%~*C5ZD>&3FJkz)BghWzD75uPGFX zWv@F8&xP3f0Hw;=Ik~8VH`UK-gS;;S)n%egd|PNXQBpLV*MEQ2g%lBZ)C^u&+(*9# z7eL`@snl{_gb2~q1Fzwu{ba4FyNrLpp!o4v&ckO+GZOQaq(2I+?0P>&OxD%XNW?1! z1K~0*2&EV|3wrq>SmK>yE`<7JDiuy<;sUZG0_MBIyBXoOXV#G@xl|<`5OGKtv7v!z z1abq>2S3#qjEP9*GKaDIsa3qh_Qw`O>bVBuqJ2IGX-yy=e%_myjo4(UJ9AxTm$7L3 z;6B~wBs|f2thKlD58se9q)p1t30%Ddc+&a`*~uvW;2NH;2PTXolzPL%_}AzrRO`Ai zTw4;F&TX)4m?=W|4(>BA2kO-ZQXH4uPO0@>4;5Q>5&Wya57gYY^v-%uK8V!h=26CtvsWy7lm4=?+zU#jh#t1lYKB6kvq}b zkIOe1a`9q4h|6d{KIWy@N3qeFNRXCTqzz1r<~A(N&ea76Fu*%t^}7x1jVI3?C(4SF zQXA=OdM(ji##R>8tGDRlckB-epBLU&k7NM?&CzjMoO1q4SGQ*;f*WpYmJ7nllJn^4dZI7vz*Rlb+=vfZ0m9v(tc%s~a22VL z8LPcnQIp@Kgh_%LIXG#NP{$W`D?dI*f`#V5Gy#thZHozRQ=@2aMcuLKqbrAQb6q0w zqIxr%fj0|daNbj{Ns=S6N5&oUvAS*)Gx=#%lwl+=H_tW^AS{4YuN3neK{!>-UmN3o ztJ8@w;4peeacxF(!x*0Sa{-_tlIq96AqZtTcA1lZT~=FV$fB2gcyYaMh<(~ev76A% zxpLerV{gF@Cqm~U*Q6Y>w{d@L8s36b{h>Jv37Iq)qDq=a_Vq5NO;w}sWg%IyJ&QoJ zb84d}N9#lvlmlMNOu5v!qLe|_`doLZ*_r>H}rG}00#N(m*2QHMSE0Sk0o1&+3 zOmVBWqv*i4Z0V!^ZO<1I-oY~bShgPbMp%;nN9$Ze|+7PLPTSq{Xc zKXp+zFvzgQvt83N%G+h+hXyOGQsJ0&G>C!8A=lAjZ*2pNq}!H8V}g_)82dA`;Zp}r z`QW}<6)uxWOJ^1MzHCZ9*4TYI@4vFn&bYkn8!Uy%(ee^}dgntLR?@WAbBdQ1e)EAv zP+tD*KJyn~+P)gPVH!fMeANGZSn_{^6^Ft4`~t4f4M>(I+A|&JR-~jL`-c@HRjPmQ)WB^~Dqp(tlH}t65!kE$I0J%T6<- z?up0Zn>ERm8!ooQ&M)CESTPa;z~Orzu%=g6GD zk*+2DlU<*Y8OM5*Rp;HvBh0vHEQl2tad}Kug&(ezez#JQ*QJR%XRrt!u#*ETvDS<| z+YjB?u}y33w2L?v?%_jGec&snjOsFkstB=Zd;aw|T>D}}SyBQ4cFA|Rb9$sulJPXsI4;7}*2t-~x`n1rwR7YzT{FMmZ*z0qpp7*}0SM>8XI!L26gi@4jMhkOjA^x2XT#F)i1FJjUZ*Ti>q*%9;<81S0?qtqF_V@`! z>y_^4m52>A3oY0)s}=u4_L@n#^{Q9#A;keZRYTmIPfKp&Fww)YyLBhR*u!2Z@;f)5DvU&E1xJjX`piUtb!4}MX^^gF58%4_)< z{DE1_kwL-My_ec$C_IcGx^pULUeX&?CYDJ&4pdG#)Lk^X{`U}h^)rj1bU#{?G=z2c zDx0W1mIbUs{`O{Y9HaS~^L1jI+Auvg7C-K97RVD0ttMfwZL#`gsV@RLz6Iw4brkgQ z?4@Lu`Z$5=r?ZyH%yg}8oeHjr6>AWf!4b$WP?sUyC~khw98Bx(6C)Nh-w>>sptLUq z6?yby$+f@v6Fb@yrz!%xP*d$!y@p3uJAoPCu;-H#kQ;F`V&D7jk9KNa9%o}V8xDM+ zamiLR6g@rt7v>i~!W#h|J^lR-!mkG&dp{EoAr4~tl+KOhZls2^j~WC_|1j6Y4|VVK z)168C?FP+nctgq6r}00Ej&zIHjaDpmKg1AKV`4WlJAJvD2a_PwndR@^LQIm&@T+Va z+$9V7C~aHbZeWlU0%TGP*O&wzdr!;NB0PzW45yPux~X}@XCtnL%WE#*y^AGgsT;6I z|B*-Eaqqysa7^F-^MF8LZ!ec#;4Mz|!)&z(S%3Y@#q(wEe;)k&SN0QpehDx~0RZes z|6}&U{NLHn|I%CV{my=<*PODy%lPK+lMP!B`zyJ7zwmRGQ4#q7M50@g68FOJ(7~b< zNL2yhZ!|TJo2rFxaC+9}AR&_tWPt(Y8~c+w>21t#eAs1!QS^MA6)9dnPrM|yV#e2k zGCQB=+C2Tg;B%+CTvs#)zFZE!vU$cZStdEpk~PgIFLLQ8*Ola!wj9si&&T1&Tuv8a z{K z=oarSv}>$&R^OMF3c$Uxlr@u~j~J#kKzk09(hi1D*z(yqIxyJ$EY`Cz|NK#5vQ+*kMOWu4HZ_L?P+wQTnLTwJhgYwo75zv1bcw|8k9s;8VU8+D=a%m{qQ%x#l%b|NZe&dnL4CFf!+zIUJ(+foh3du-b4D>Z_4=XzEJS73HkmhS}N>c4Zy z!I^8<81&ZioBO3&OBpY;xJ9sjY{<1s=xos%0QS4m|7QGZT?*5vHQZgMe}KTs>!?em z^f}6$8YR3IYd{Pt`V)Hdd9UInDD50grNsuI-rX%zh=FtgC59S2AWu&+Dfk`opI|ka zsDjW5{i61h&EI3n_Ec)3+XF-Re75{ai&xH-;_ViuriRbJX`Qp|9XylNo|E^}T3&BY zj}C)+h6&kjZ{e_g6efW6`Y`0p0dCkxZ&Bq&J%u}_$|RNEJbPg~vnGpBbbH2^HHkFl zf`+IH@=1?ul<5&xB{)cv?D2j>=>RTJ%v`bG)m@z_JKCyCDF=(lYH3P=5w5(jx~-pk zpLVaERXIO$6h7NkTj$LppwD7Xez?56%TcYVuwC_H^FC_vUt9F0K!uPf!Z}UF0@rYf zIGnrs6EUtJO1*GN7)zD}25)c&O$UQvHbSPWepC4*vz4P^?|urT5bgJ)B`}uGhor-U8SJxW;`c@aH4HN)T zJ9C_!cZrz(VHK!pg)JJc!4G-WxIGs9uE@Lv)xx?@50xG6-SZK}1=(*)Z%bkyt>1kN zW-XJ+KgdbuA{1Eu0d4f&aD~m$;cz=!o3&NIxXcshIeik=xgcdg;{P#BXx2z!z z#fm)-@7giEP-dnA^pWdPgn^s-H6l0}@H8d2iyeay=%;hj#;l2RzQd`An=z zkroPTW@U2QN6Be2&_-eCkbUcoQ?OL4J2X=5Yos~sMDlps;wPK%&qLbF@p5q*pM&{r z$tCqHtlT#=cp)n7?@f0f*l^T>Z9FAc)G$ZEegooIbZg+madAD<0J;8OL5|{0Jw!_t z;eu(JXB_6tHvcCnWmgD2Wo81HyW|JWS=IaD99Xy!n@MhCdUF}OD0SVgw?Vr~{A0cf zOg0@QZ8vtdnaxtSaoE=WlQuzSiJ`QqJ>zu}l- zj8&+#>2>O!MW);k9B91~Fs&y4G{>3??1z8&$?)hZ0Ef82Y+`LCei)NhH5y6WZ*+x{ z*4|RbakhBO_SVIwCuQw>?kgj-V;95XVZUdJQy}jKK_o6G@gur0@7nx~M*z>;55W=$ z(vCGmnH`=;OHOps)kN%3FN8S7hD}>eM47+bsoRy)q2@PI>Re}<3aOaf9mLl_v3&R= zg8wir!a04zTp!GX)s|n{kAOd#D9Srd)i3~y@ynkWUny}|A=Y`^GaOdMJEu(p!4jr1 zW<68J0W3mB;}VG(1V)lcWumycPsAOqZilPydeMS~kPYbqrIPX%nS%w*VAkr9=Fq6N z-}UMgXSFWfRGzi#HH;Mbs?4P_oLV!f6dK7<+PvemtRQCu*RtO;Oov!802UE#UbpLI zGDn7)mXI*GI;3UHm6#+K7|wFSATB`sC&&u} zwn)K~1rWbymY$4II1@C0CV_aMpgnH&GdePpPJ{_e8!%`HFDCd~o0+({!Wq$Y~0cZm1>?dxv|@L_e*wMl4;a zf-}nSXT@pUJ371K=2;UedmwLpx0_0&Hwj{+X zmBxhq40ppq$|mF*3j1-UdH0{^tEWY-_!#_77;`{1CDRe%5fS9ux_=EJ2wZtqo}P;j z)OG`oU^KP=X&iX$wKRWG&7!#I^_|4Vy{&FNH{F?k?w9{}ZXjK0@6h;wUjWvKIv#5E zRE(oKZ>|CgjaJ{a0C0m^_nm}30vWIl?o^PlwO|j%3Ox0dhWV{LEAu841KZ=oO1Oq; z#x=KMjaf#IB<|WZXcx2)Nvg@g_4r00#8ve)OH=`@;hJf2^wr0VHH3TSan9sVzQ2T& zGR}wiauh-R_}mFq=I`xY48q9zhcZ~(rZL-ld!=LyHSawP9xN{~^(tEa+iuXCW{s}| zfEI~Zi{tPr;Re=R)fvN8DP9xUuwg1*t7!rdG zP=B1Q8+${tx%H4WCVCodGBQ}tCrz4(6JyDGl5_ha3*Db6o z`CWwFihJsy{N9h2??;ZCWO2wJt3o>z&#*9RXKc4dDi}0mfX8VI&nO+UR7q+#$6F9? znc`wFux^eARO@raT~xa^ZOHl8A=#&v4MxQ6V8-r)0q6cZY!X4QW|8JDHL(CT8KQs2 zMa;_eN`3#OQmScvh#eX#b~t8xCWIMtWwZ5$>>Xbd5|GT)i86vbb4RrcGYiKQr~xt< z)QPU$t2S$dLI_YkbPee}eTngLnWT2k(`w6qA!N>VQgoe0VF|3|ZHmDDDg8>HK&} z0ws|CYm7dOrMiiXmWlF%URIVTz?~?5bOK?TJ*7$AusWgUl;)2z$L_>9^dEP8N26^x z?`|E=v;9r@#6Wfe6L0@rnUTndUSw|$y_Ct=*VRWjKWTS>x*hI91hQ8p6^cev4hE%RnB!pFkoq)mel zh$zONkM@DkhMd`yboY>W{q4ru8}!Bj>1K6aZ2m}`GO$kT-$)dzO$1YK8Y=pshMGqF z^Is+Eb_x^}95J;6Kkn{}f)F}gm5JkqknKTb{k8r{ZP`GSD6?COqs!TIua*V^(FVz4 za5RT^%$l*G?3mHoZNK35xwn3G-eAivm)C8nz-IVJSQ(5zhlod`f9rh04mppCJo1e3 zwFllD!yM#qN7|Y(ZK-)sn3j+ghmpPm`uMDVy2?npMmST|HAY?+k>>25D_|Yt?Q`}Y z_pzR z?3y6K{q^~fi2E)DJ%(HQ`a(L0r{Zwp--PNF6HSfp@8o-lqJhURQGwh?eOFkiT4wK7YP@&mD1 z`IRNxX4xN3W8K#(RY;k~YUKd0#IF!w*+FQ{tHeR7sPCmF4wX>xltBy@Q#kYpZ~k3x zK9rm9zu0cJowiw9C66{%rWK-tq_XPdq}em**FQX25rtA$0M7fQ9m1*t-EuKADTk>gX)96f3zy$JKKE5423Ub#yz5_arZbNV!z@Ls^^J*(cEwJ04e3I_AZ#)Kp)j||Vk9_113riMoHYANNi9L>=(R&Rd4_IvZe z(YkIOT*PYF`?XQTcEwfdkL=$NHSYy9}4Wj54#QTNTYn|hg98}!BrOvv3#0 zGh*MEot^!K_!-CW5;DG$-a!MZwYfJQr9b8WHq`U}K(YDx@?P?!V|HqFLqX!x>f-l#^ab(%sDb|# zV12JD$+EwZ@?`&+Cc*Td0xVn24kwzCgohXOAFCNN*OL-ND`)nU!jr4k=b?Bbn$9th zH-2EG&`1n{;5Vc&tP%kpE_=vKJq6X}c4wb~a%$`u@K%>VMt}=nJ+picuV(yRx&@-i zMQIAcJKUrDNLW>IU#L6Ya`|uexNd3{OId0 zuIFpZ|Lem4<>BSmrtWFj*8NuQ)B^c#mrB-ys9KUq6ffVvi@jDg2mgmZ#ygMSoi=LR zRJZP@3l)2m^oo@4TT{k$t?ph|4a9TXHdJ(@^0IB@qigUZ1(lvc-#D%1MgMoLsb&; zYMKJay-N7jz{PUW_2?7qPzkMPN(%Xc_>_i7b?qoi#J!FAOm*D04a}ylUTF+5BkSq@ z3JThSOZ~1@P-9Wz*j_6e!)jwpMxgCl_^)Ht1K!Y^$@Xow-;> zcV<;5OgIl^KT%OL(Z_jrKO(qPob_Y9q}8o_ zhkw@|hi1Fbx~sIA2o@fpNvDgd0uD;S2PsS~hd67}Y9GyFzno#0hRv5GsQ}2XttOK$ z8-6hu72DZ?5R1zDPy7K*u`D>tU{`#&5R(%p>%$ipgnOHyvyGGguATEaFpkO$hJhLV zrg7=Ad;`nEX%Snoc7*W_`H`e{IjV3JXh?m8pZ| zvvsn}PKeY@!mKUUShLO(Q!*$?S4!h@HAf}N`-zNjip(+uQKo%&SRUYtk- z8ZxZRtsNq9j#3H&-9pUpn)>H+;U|TD$7McY#?xQ^bgSxYUA?CIAHe|Y$>!<|wwW$R zOl=#N9USMCdIt&fH$e42kadkfW;jEMl+H;!Yh5JYCIFSRUQDdu_=t+;q&Tx$@UPBH z4MY!rLdoVF)smW7V>H|!pA4J?MZ%Nz3(wowz>6$i?ILcd=p;l*G$v*$KpZ5Yku2ko z5G${$byVEu-YlXhS19lro&~)5iy4c^_#6bwNU6Zk9jf#A#9EVJl9KcLkl1!;g>P6* zs~_|77KVU9uPUtFC}^(zjHM?b~lX3Qqhu&wb!uU zGb+JaG^ETB48bC%^Hsw2ut1l5a8wmp;DVl-2*rc`kkU~~F}oJ^oFtOw0m+aeWU>dh z;!{G_I@b1@1rL`(C4@IHW8G5~GJEsVn8RziZPg8m;KpKXT+H;@|HLVr9Pp&%-fGrGnXSK=2NN z0~Lk8Al#dBYL9;~J+pUzh{Ms`?%gsXz0zrggc@l7d8gLWSedLONmZn3UTYX@dakO%bQR=LCL#6O(;w z;x?Db`$gtcuSCmtE{mDB$dWW&5UL3Sp>qiXZ<9n#cFHG$qBF)#(1yM6><(*3W@!k7 z!I=vl4bj0B!M7Yu9xrx_9WKVk`{7c}=~=68R|RC_phy zegjpn+<9sF75LkH_%ajQt!X2Mjt2bXUcu-Yv~!7 zL0`2(gnwE=@JJX|q)=#a5N-Yv?ncV*fd1$Y$r%n*9)JI{0~8}sG`Ipj>NfLsv*cN*Yi|QqC^FqV)#hGv8dSIIaM0qB?e)IgI$ad)IIah z#3Ns~KGKr))psR3i6kH#`w7D=xwv@F4r*dA=!ewh4$c)<(K@DZeTQeuJxRa^A3#Zrl=y|R2SBfE~qQ8FS(}%Vhdotwx3`Zie6!dVEK2w7Um`}^p_t0!S5(hU?tZz zGA@79l#M_xw|Ryf$nTs}=BA(|u9it@JJ~)y#p10fhshKx0F#vv*?y>-Ip%5k-{4rQ5) zrGhJH@rJYer<(mbB<@yI5wGCVOGft+`GD1wt;osZlU5bF~Td$R#R*osXA=e z4*5RovT5MQ(;}s>JBxyL8E7GtBBt!hChl$E)mf zQ&*d#WSm11^S2AMBhYt16(n{*+?U{*Hj>Yh7i#sYv2S5Y?wZ8e^#0F|ofOpT@d#kF zHn*Uw>if_B28oiLNp-r*Z}hjBJZ9?8_D0#M%uu%%ZZUGq-(Y_hSjJXyqW!pB3t@%p z+Y{KF0Pe@KY7SC$A}XOx+*zeq-T14xOGeNLp?v(qpkvV0ae0TT(|g6#oncg*z4Dxe z4B|QE2`Zexq#rg#8@`g`M*3@JF9~F1<6|$_@gv_Kz`D@ZE4hV55h}cWUFBH0Q^1IA z_FqF9YiNnC2t+@>8AP->4n>LO@FA2sQfHd6dUAHWeCYW!#y(_rW_Xe@Lz|=^^h^e1 zV&WW#8cfA*hOd!QSH-uIJqb-(Z}+t!bl1cPr-+`DAH_^~Ttebj7SV9IFn5SGRfJ)Kk2%LGn;7orsu zTS$8y=-ey$$j|c>3H~Wq1A{1}A}#8kQASx%|R`b#;JniV|NOSinH-Q$05jf-FW8434Ew=PM?9 zmSm9Homf3vzZn1fW3s2#0$mi7TD<5^()`tBvB|1haupG^lAK5~FR=7&NsBV;#II~F zjGTbt$Vd%=Uhl;c%U9oz>J{AB3*i+p!$7GqC0s_CV&_XNxtr)9P+XR~E;?4lSG=*D zVW^arBhvxK{kwDuvUj3ggeN}wMHJ5PmFZne(3h1sb?Vdxy(YpzSp*8_f|8Zg-K|@& zv zI<|ql_46b*gZXs4JAYDfC=*#5lObT~vBw>D0POCL$tPg?3WS}Lj3dBG|Yn|KO z46+$t&i})mS+8(G@gTXjNgdTwc#1Fo2WO#RQdWeaTi2Ds0b#lY&|*Em$oZ)7$E$x1 zB!IfR+^x18I}D^ZZvyV*y68F&K&f=pbCi0;5u|y1o;|;>$^Z6$1@Zs%`3!n;IiiQT zc7dA@|M2kp-0S%tHaTRG5bf~v!@(d(0N~;W008q1kyHW-iOK@$ZB70!lDPg`V&3@w zi_Cr1WbH{Mk-L^^pf3pLt6g2!So(gYB4wmMR*Roy*R8XI_2pfjmmgocsGDMZa}(l{ z20&mU(BX_71*6>B&VO<`h^)U*q#}twQd|>PwCmWZX*7RhPqDFYb_d3MM7R82KIQM% zR~I{O z8VZ<*dm2u0xuLDughK0Z`oEVe+{~T;onh;vmua^Jv6p^&_D=F_i`wF0I-@%aKo?NL z28s*rJ+gQe;*nwCqHN^c?}Z&qwz|ODq4OpRvtTHhVubMPGifGC6j5dFkYAImUXeU= z=<@}<=1o?)`y8Y$o`d&7?*x!4fS!gfQu=x7SD^_QmD40nyYvqSnU&8Mu{&!+kDs?l z{vX!fGAhn3X&c7ff;++8-7OH@-QC@t-~@Mf3lJc{@TA61(Z4WpPdQSN4` z#vrSs0yg?-VTcA50xTampHWF&QQS&}=ZGFWcEr5nbaQiw7%SIWeeI4(q~9%jF0{;4 zU~ZTbli--KhcLSQEzZ!-s(EK8Vlj8VC?WyF+JkiM^$Bsdno=ij48ZIybdhS`1yMpk z4Ycj1>|f*_wr*mjB|Z+aU#G%yN_W3jm=1%!qm;IkRihXFmI?+L$|%b!B<8zh2xHcw zZboeNgNd$$UHcrdsD(wFzk)vtuE>>LSJIT-JN_*=_W%*Wu6RN&7gw>A`Lt6lhb*z- zB&4mkxDotYmNw}VrJ?^VEZt-`d|l5ZEudKed-?fhNtQf+!Bz*a&4&$JHVRROY$pJN z8_JqFt`^G;mL0Cr5aW`VvuNJt_iw8UNL$qry~&$p}8t%5^`y%#7(%{Y5EdQ zG=M}4DdWhow&aFcVI(ZqlHni&nkbPglTq0{4~zj!u;!*ozeZBWAm(D?Gvves-y68M zm)-KTm+$*!{Jfo;hliAqd9IFp4WIG&PjlZNR&D(jV?$(}F;;t5!|-(U^pKv&r)#?# zzOP5R*}h~>u>QjE_DEV^6pp;k#QMie@*@H7uAp=KY=5Ev8$L!SfIE|oHC_bF+S zx*w@FoL+o-MB@d4pe3|CU0#m$2%c-t(Y}69ickLD{~1 z&uRIDcNf(?A+pDMXY%~MAuL{#G|`X1s>!1Ath&QVJpWA$1lYZbg7SIm&10C-N1RX1Kfk}-nfi|!atyD%Vp0>Ij*mxN%lma~K%Lam9 zdHgZMVEFpe_7q+YHsJ1{4#L5>Jn1IVf1)OPG{HFluB+J=6+dk3_B*5u3Px(fuQCk2 zj(ihDN1=ns60nWHh5*FU=Z(qfCNB=m0yY)EgjtrCuJv{N;Nq;vgT#KXdkyhRj$D7) z#1hP529y@x;5oT@SX9oVQOH~Nd60Yggm~PoiCn0O0cR5J%M=$^=lj<95J}f;-NohO zh54H{9iP|}IE!w0$l_MOIICtzH@lV5^zF{Cu-7@*Ui)JHlnU38xjxZW^9L)8*r-H? z`Iz*~>-DOS@4R<{Dd)@KI+Cmcn*dI&QU0foaM#qnN|-*C#%XX|{ar>YFLYqc+oyAU zIv~fVeb03d9=x`?V}nHWV){SVR`ZRHh*6*eUA0o9XTLVH|!Y;yNFo~$b4xl1YHmZUV7>2L@VRgzE0 zdO&j3EIx<)Hv~`muW|S>H>BP%pA4#!9q&#o(j8h$tB#F};hFoMZRE|h6wh!wQrn%<}SRxhT8>en&9+9h5X3`%W?v5SQ3XSHwGMLmW z;MEOZGzn#bYY%(qT5lrr^B-@m#19UxSFZaE*uMQ>zaCk_qqQ{&-#fWJIDSN1rAxKB z=VRvzE8I!g#@M6$tf`okQ5rEHDbvc7)`SZ|j>$A%+_gDU^dQ&P1m#c&1FGI6fJ8K__@Rlok@10AK!St?zGY?7?xNuhZx-Pf9!1(^2)*Y$9{7H!BS?UCJ|WO^tI ziSUXYKEqLIF=qmMG#(h5Cl-psB9vRYK1Qg8OKbrkXuZ|qpzqBDyDuzN8tgFCd^m8J z1P)1w9-yy&+hBo@{5E^yWN!52)=Z(KohC(E&7Iq;7ViFG`!&XZT#pel z0ag>D-w-+{L|0G@vf+Xr7z$(~B?6#)7{qt_6KY$`(C%A`53sBII&r^5Xt?RC9On$# zIG%!VNKTV+Zo85KnMK4}FTIy+1%uZ85Nr<-wqE`!3X86!g%r+ct6&-*N3PxAg&fQSo(9Bp@ zm;Rpt>c1!2{~`kY$3*+T*v$S@Q~Mu5>i?g4_J2>0w+HZ9;lX96a{@x9Jb-Tt?AKER zp5w3Q?R#M~|0RDsZ=K3iTsj-7_W?CaeCoJIQ44_KCDSMv61X}Un^+Wior@mZU^bXe z6zr=xyX<4gn|?=K}6qN(`vrwS(V#CY{gup!{wCP9Qxywy$+#m7_6NN z<37%Ap652POkijnYc||E)+DL8i_XkZ9`~Zc!j6I1i`D5E-a(YZ)|hQ@bi4vtE5U)I zT6U#a_B1>qrVO+&u<@>MF^iGsP&F6~av&_$=M^ZJpW%x?OS!3xhGk)1OErzsN^9%O zd>!i_Fq-nKcBi-wrPb-6AS&dM-HRG> zm{pyX(82!>P6J&J>4Dh_jE&vMe@2ZP8d_$8B4IpA`}}quFB<6Cpqu193LO!GdEU0S zXHl8^J#p2fDs-9yq=-K2t@4hMA-A*<`1JcheHR<$Zr=BZC?)c2(%noX3aIpC7EP| zFdrG!cl4sosEE?+oc7|m(}GAI@vRw6+Q`7tyyR|sGhiN^(f8sr z76p#<+F&sd>P0@&XQ3?2VP zjQ2~)FZq8c`P=!?TLU%eCnDRs0Ms;WfEz2n2sZxpFMcU8(swj7u+?`kq67T;D8lt^zykhyXGa&d9^<>kpROEoa&KBDIfg)}Q{6i8u|Q0aC_4wKau ze~*3qkP-!E%Ep71T@LhDrtvmXSZ67GfjpW$BU*6|Z`4#W$>1NHiOe6hMh8IyNC%Uq zt^+_mLVo_CgNKJ?dteBs1J4g{JMnpU|HVQ~^uRZYe*^2vrc3B`kE>FE1RGgeiG~S3 zPRdWjpMxZ(tq!7#xix|G>%D**@b3z{5hC-iViqGEGl6S^$^{w4L%mlU?i>Lh*j+0=F&za2~YI|~* zt(APB42cl2l?Zs03ZsFB+?6)UmiRRAssV)_R1!ldCOaKtY$5POXYyGD3r-GtTFv|mqh9Gnd$QFm7h*o6AF}8j01Y@vD7Qk6VXL+Tu0+&9PDZw%7Uzr6)+CuGh>N2za(N+qFH_&aTXp9W&vA}=EbT-cx`-WcwnH7h?*W!0v~=|6{L!N8 z$;Trth|eyNSshs`ZB`N7^Whn_iEY!}f(C?3sx`}-{mG2wETe>!2%?5m=Yi*eGg)LV zA4|tl6^i>aw%<(^<|tBS&u8)$Bha;^?S<{v{HrnV+3PF(1H~g2cps23tiVqTOwCAN zcy21x+UIMPiAy=E#1H3p0}Y<{MlwJ#_m@qoRYuyq%dl6cfMpH8(ivzJ;V!MhC?({b zf0pmCb>~;0T?)g^g{KAYLbrRg#EtgZg(LZro?;kDqTN{m{@o!-Q@|?vlT#N5(Ur$l zmKW+*H*YZ=-B2)i`8^-gIQ=azf6_PYk0G>C9?{MjAEGSRu^)F-zL~<)8jg0D?p-t{ zZ_<)Vud#*jCupl>97{T_rAy>E@(he6n^Ght&h)OTsWGYU&o#GR&T*FlQ9op@^y&}U zr!zw{Z@S#pgPV9cmd_u`U=h`vKA67a5V6aXEjdMHz~ITm!fH=NQ!1@m1R+gDv>e$| zAkb7;uyYgY>>z@yioy9_h&3!JQlTl4YiJ7Yd(+4w} zE~J6J19__x_9J?0%8$MF!@0B{joYVn`3*#bP8GH4IrFo|aL>2G6>HR|Npty(*_cV? z?LoYIp5!8AH$dstt&*Iv!8rw~z&6d?LnSh$u3_y>3bi=*&1X?90htvm$rCm{Wd}fu z_`WtDigkI~&)+H$MzrzLY7}aMq9|Opr+kvvY?F<8w&-o9IuNWz5_2TBNOqY{inPPHstS@W^WGw8q z2VLqDzrK%ieoZf^Ek-OTPvdYscy2#G<7xZS@P2>|-04Z^4%d%N9cOMZI=h&;i_+?7 z+o95|6g+T-{{yFlB39t**5=8lSiw>jB+6V8EcW>M3&YsKFndrJ)l#W=2fzsV@-pQh zEbe67cao)&VWAQcx-vJjws#b^#*`@08Ca+{_a=DT1=nNGlz9~`I0hDWMP;lst*9G?9%?rR0--)4HO0FZ~JofUR^&KL`>$thNk8 z`X>ku7xjEs`e*z|VYrb!oTnmY_NL>Z13oBn^TnirPImFQ84iT0JHgQvp(7WbMEt@V zFY688rdPOQ+2e`hvDYOSRSgK6idj!)eTfV@#)7y73MPeq&kGwyJ)!FYLVV>PSKAhg z65&C%@m#ee3G80@)}hOysH9Of2R+@Kgl*((pVTAb{Of4&FuKq6sls}y*8|032~V|( z;KzYN8tV^cTGhQfbk?#)Yz6TtIP-vrK`xR>CDh-nguivzIoO&y z7&|)BS^SOp_Qn~_f5{)}%9XWkml*(uK-E=|Ot1(trxlc9DfL_hQl-+8lfqIJcE%XG z#n{uboUr%yV?;3prj+_C|E4?MfrIrO$;sgBhDR2lO(t=3!~!C!um0p%M*b7viPOGu z9?xVLSjn~D7M_^L4Du+fWV?tzAaAo0kB|_VHwR;3h1*@XKEI{l=1`2bVu@H@u$d+VZxzFIh zLCD1+?1*#V!ndh(Or`A6C_tOW;GD9b&8jM`&kAW=_^WbCn(huiVs!*6lQhi5G? zvQ9Yx4Z)?I!|Z}Qr$W_3t_K`L!}Y8nwMWv4s&1T?13G1>Fra^`2Y6>or~e0i}L%S-&20Tz@}=eomu> z=Ib1YrETp~m@XMLHv5Fe1#s)VPRI5js7*95bx>mthe|d6=#2p=OXAIWnT@AAZ&T37 z(9JTZw_;r2DHTc3jJG)EGotuncy$4GrEhFtv2)zTX`}u3Ly5gbe%_+Jah&~RACg2> zgM239QEnS&&y*r3@!OZo%Zxq`%+$tg1vXXKW8c=%L20;EH21(7@OO^0O1yO{HNz+! zeQCQO4=t%5PABWm#SyRpjt{M;NlT5#>(9`JN~?J~sCRZ()$bl`W+w~wJ7;6U9bnEX zL0m>A=@(U5EpGCp+tcZ#)jrFH<+m&LJxl!@D|pO_>A2792Dk@2JC9z#L9|8#cT2~O ztqzJ(gX(rO5AeVJqarF$^Ki%cu@B%iH30YduRRdpV`j!ycE%3>agWeeM)NR${OKOi zf|flDa6#v9XttHY^8t>wgL(}8mqwdgo)5N?&-tglaU&INQgvnm9Lx)JGW|~`o-aq1}OiU86?vn&4QhxOq zFawPJ7fgGGMR?}L((JFWeW<1F9iPFBl8xQoI)<^Z!oe`-bA^nvXTOVRZaK{MbJQ`>x8svV% zHVP~tY@|M|{D^q-L`*xQdvltZyj&1UjvsNtyJ> zO4|`?n>TAnL|-2;G|p77P)`~x>I6t6?5yI#z0MC0p{UyZr$m16^YFjE-TUgaDSofJ z%e`FHrM3daPoL10)L?+vf{Tu-A&s)VTrk$AfOGAwfFVQL~Lnt(#ewvXQ3YK0lJ zIq3)PtVU}*W*4XFBE%_QObMwv4ES2X&x6A^Wf7M*N&Vs2l4-=J_C_4zsE)~Ggu)6v z>_vl#1|wwCY2YBqWJRl{#iB0T-ujlR#A z5S%jIU`8A9qr53o6=V77g=h;5R$f2ghW2P8%k3!)MFJ6g9}l5H$xUz$SOZP!wg$!g zbqx`(Ay3b^Oiehl%Ov4##NDd_8`8aGhnSgZUlnvzos&!n<-R*m7(>$8L|v>YLM*0l6w@>8Y2VK~?S1v&`LdR%xs&4p(4_ zFeOoSNfjWP;jr^wy+54wo8%w+!dxiDm$G}&c2sP~d8c(BYbIObmiA@X=7vb5QZ?5D ztBkSrV%`GAjo>LiT4yaHBr*iUHzOS_NG*(HRnK!UQ!|O>3YE`e#@Lnz%j&a4s?q~V zrTFxZLk4e_6Pb@uN9y0cJV(O*lkFoC~{w_kKlJw2&nCOAsA zqA)up?-o!bNoWpBtV!dowStk|5z5sLtE#I%70I&Mq~zgS2Y)Iw$n8pD?=nsc#? zNBd)3A(3c_hGyAM{mtwB>T`q z&3@VRC^$gsjm*eFd!X8xu7@zY zO-l()oo@ohm0`^30y7;!U2=tHhFMrfR2U4L(qa~=2W8D9fu^hnS5)5z!xUDn$B8neRerwXi!ZvUTd74+yw1 z7EZt4m)kI^U%LoIg$ULx1zKs=$W1p&`-Y1bwvs6p;ffniv(MoY zgx}h^WuQEs-EQgFg&V{4;`E1a?%eC-Qyt>B)8lx@+6VOwx~Ab7xFkg>j1ra-O3*jR zEX0Dm59u`&NkudPgrA!@^Sp7VJ>eaJc#MT(3s6#^IE_H^MM4R2#`OG};0NI4zhtcB zDtY#NQo~*Y>NylSNeHlQ%S$uY35K#f(V8XT2=BB|pN}%IW}GCaEzAI`u>K?HW&~k~ZNL+=fr83kjOOn<+VZ z*I~9UOPxYBGiP6O2$nu6*FDewu$be`)EePPET|EB6g~IQWTHte)h@X^{chY@g{?OlkVa23k}4(vu+jz#E~T16n~J<(NCk5n3feqH7&koWPOwYox@XcTpI(~UKv>+LEvy$2VL(K^v>PCYA% z#C4n_7NFF$tHXY{f$Vq%)3Ld0k4dYkS$!ktMMJoZ)L7ag8H_!=T_S0YI8(CAd2%U3 zgSJaK@gHQi9o}tcca)ExlZRONQpt!Ac?kO2GbkK-KgqTjq}6FlVPy9>%$B%NCLr*kM3hL7dZ}Y>3%9_wSLxIQ3R+)7 zH#e~af?HMGr-wp{20Z;YcWIpNh=XG`ALEnP^ODg5#OuE>{;BGWScz z^`|C@ce)IE)Vy$EaSir!?|o~|t9>{zi`q>`YMmJE@uOt=qU@c7W=){xqJZ~gET?O! zc=DN-go!p>qN$6{%a3zG5sN?o5E^wM)$m6zaXf}+7?k!uzOAe;qk`YAEl38$(8Y+3 z>VltoT-zgQ`V`hz+;2dQVU5rSlIZAAs@A>#S3bi~Cs1=Gr|+x`a8~mH>7+Z6`5wr5p4QAC&6<$F}DP2pslkS+lSOa{2((#d+Ju`3D~ zL8RS|=&R4o+95|DC4F{xc2Gt<7h5MJfHvc+8X+daBI%;rm3riGy+0iZ1Y9>p9W>U@ zw^70RMY4JYlij369`ioPe83klcUTXoMsFo!uB1tyS&`T#+|9V3 z`Q-P^BtDGnl1V)8=ba})(1U07@!Cu^&%e^N2|oj&V>hK|f9Iv)0WW5pyS8{qK4O9Z z!~b2sxGYm#RJycl(WUwUB4mM$I!s9Z*s(DbzAC9kO-w1t=f~00=VpJ>ZN{c3p1I_s zbWBsof=`c*KWq_!Ef_R+X<{-TQpR^&4NN}XJzRofX=fn|$!v9^4|?y8{I7>z#TH#VNN3D51jrUUfQ4V`IC&3YNVk zROY|rj}`x2NBz|@1~}&b=ku$M3a}Vm2S8JY@xKykzuGW<$^S#i-*wbqO1OvBrS1W0 zekBZkVZr}WVr1)TV`ZyvL}%yz*Pr?yZ5_rjV=`cbNP*`(A|WUw@k^1HwO_x=M|&_{ zO4&iMQGhNAL@b@Otem`<7d$KYXWck8BB@GPx=!dg-XYU85-ru)4Ww9r2*LLrXP<@tNA zEF((O%+M*DR`rxx&U7%eyPkmQtcYSilaDWpNF4zb^oK2{b_O(F!bq#;%^R|T@Liff zHEhO}x_}}jxMQN;uQ2Q)#EkwJe8Kq*sTJ!2HO(~wQda;uNjgFxAc((Tyqadc`F)xa&m_R=5H_+#a6wmpyVKml%u;0NpaT0 z+r_)cHv}J2@Wydhf%1&oSyi06HER22C)Q4Q2g?`9zRMFFES87#YYt&q$_-rO0Y8z-0H>*M~Vx!O2+ZEB)u$lNye}vzryi%SoaLGD2g% zZ{fzcc2p2=nKKa$gUK|~c}o)2R2<9pT-k~$*bMi=9`O@6K%ehL;ajve!pivIdY2WfP8H_&^6xTfO@rS>8e=QI-Nz8g@j zEbl;q0%5vmm=9xuqqAq9Ys#)ks)!hJ)Xj`Ah&I0|9P@!Jfk*lrI548x^I{c(-Uz6J zJ{T}F+G$v^-lABQk|N)S30u^RnX8=8%W7n!=$yRE|H-H3vOBaa_|d@Xp$t7dCk2=ix(clpT#cBtfEg ztNAgV5t|u-ygORm-hLlZ!9ln9JX~aEq#?nx{4W^>XRWmYHjL=iUoX@8h+VZ(B5b{- zgvIEsJ;x28*p&yCYZ7QbZKgs*gd;Jh#Z=O0gi%os=3^zm(>0Q`JhT$(`o7Zd_H@u7 zLoA(2V^_w|C=81uT^~wPBtucSxJdwynEB1qGO*k1V{6 zlX*9eMWs`9)h6~c(AAKf0|S+pvgqk>*ld5`Zk|7yBTjQx*j8Ej+H!@Px`q-Xx1Qbz znv}bCl;4J<1x}i-JauGgR-c5NJ%cRD7dOIIo;}V(m~*#_axW_9jjm)3LKd7Pik2`L zZWzg7Jlv+Sug}J}KPP{Bco_3aLC6|nR}$xL&$Eak8wb^~z9qmaX&Ufh8x)Q)_xLOC z$dKHDU63GF1=Z(r7EqMh4qBRE9^?7%;;>2uZ^2O9;Ol8Ti5 z9Q(GPcA^dxsr7)|)Yuv}m{it3lY}~HwfNx->nzKW4KrTn{wBcDKA0P03fYk0EGGIa zmD#J#4)rvgFL&NyWGm~y$F6d!pEhXj=is~V>!q#lIj*p@-Xdq0+)9tFRjR%_D{K`l z^0Ya&!Uv2ImLW3}*pJ}&L}qL>8q;XO`fkVyfxn#fDHMu(NW;_&&DFti$v=L7V`?mn*b<^g-k5h=g9P2h+lvD5a0E z6CK!twGylZ)oHaXY?Bgk8_)RTDKnv9djP&5zUWUA(l5Hyxwq!C=^1RZkcTBlk(Y+2 z&;g&vR4UlZ4_J`pB|$p2ysLtT2yiG^aLrhesQA6Y6+leU?yPe}zSN3=|5Rb3l@(Sc z_wraT#u)ijuN%&ct;WP0z)?}S@5hyCJS%8#F@Z2~`&6l7%RU>+>&c;?6H~D2t5!3- zo~JmQUz*yEt8Gc6qpNpUhUBRl;!V{vUs{O{B2u<++;wl!)o|_AfV;uk;W~JFzJEId zd}nQJw?nv3fVSKit_f?kn#;QqGnf;l9y3Y_7K}*=3i=eigU;y@E@9H)0vNqw}(WVGny+8z}3EK`_K*VURvg8Rr0>;MfqD+$^^w` zPR_2{4?io^^Yi#+f5!QS%(x{N48?LFq7S49X3WG_2ZU%B_5*(@mTdMr-CXN8mK@q3 z#v0DJnC3uF``SVc_1zfeJ1t{;0?7^V4;mfsPk9H6cI1U{locTN%ZJT9xs3#v&E6oI zYq8voDVshR^^Ng#SS1VD5ZXk<4|9&EE^CnD7}t8doLQMNDl&ql192Y29%O+ziUPO^ za`oL0uTr*8$pLI}H)>BYTXVX|Cc6Y*=s6w6u-6%DxFoPflrKb?5j+W7me-jAi+mBxQ_6`n{XwK$$sEZNsfS zY`%L(OViO0K2~zSU07hnOh5H2k<@KHhkumt+K2(t=PV=0*z|f!ooP7LjTs_NdGGr>g-5o=45U4mpU&Hdh=iMhdSN}L6~j^B$0d0z8F|At!UtI zNerD_>tJlS)VK&03UJw-E}pOEwPz*|=e(^aCp-ae&|o9}MK2P$*RJ1zDqFtVft}wq zpK^#3%dhl!bj5zdY;-njk5M)&RXHt<_!{zwll^6qwE*HTJppi>x4hV*Rb z!l!*Q!CJ&2`-Q@C7?Z;hN?=POrsUwTxPWc*zlg|xb%iIwmiB`KYUMkCv*oW^;O~bt zw=pty`~8gnqd(kR@!WES0qJ$UW4ox@_WGp2nhkfQGTWHJOdYu&^ZDb_f!e1ep2t=) z>gNseC7JX<8xTYL^Rt`vpOo%*Z~JRkE2ogf#VSkc+rBxCI^U$I_W^TUPvBN1EJzUC z`>ewgs^_i@FVZ5B#1&H7SWRjMX>BLTwvezllU$zLbh}Zx8$+heU?g-T>%zAp6SdmD zBptJvO$|FBz|+H&EHG+`j=3PPZa}zJ=THT!vxuH(9AUbBHbL;ke^NzR@CE|a50%2} zsr}(L8r%Hykoy!{3TrEA5wX!1=oLFU?bFmXC{=uk?F_T+o~@H#Dl9Gr3;lHW9OdcN^F{!!JU|Hb;RQb5dF-wp7rck4d)l zdV4*|xgFaxaF^lR^BQ%$9n?_}lltd79pgm5jn-`@VRAgH6p1aJju|xFmv4h4&gd!5 zs~_B3_97$I#Yd*=-R?0r#**u2Cy{pFZOAR-Kq0_^Rbw`P*=LPf5xvBv&R>O7RQbSa zjT_v!=bV3GY;z>X@nOrz!`{8Gb9+KYW3{7U3a00SHMxa2jiwvpiXK?Af{xrqw0Y5-1(BLK5P`G-lF*;*U_wkUHzchxWX!)wapq-A;- zkb(eSqgR4V6IZ-K1&v&)7XV}N6T9iMw(1Dbc_Hw@U<80M95PjWY2&h%3zPBroG6JRS@paB~gPp@YzB&)IHZ#h0ENzF<>^Cy;5C;aSbF zvZ3vgWRjp5TRG}8ts#WL=^V$Bsp>Ey^s$H4%|g||QW3RaJBU@+ek=VCP3Z2-MHDwC z4iE9CxtsGm{})O5U(oN)jw6AZxf|G7*C z`i}p#Ode{C=D*~RWlB_#mh5FfYI~;c?_58Duq84VR8>WK`7#$ko?5iS)?%)}WG~YD zZnIoUi~q^?I`*FHysh*VP=2j)f{RU?Hy}wOWg0tPR2!@|kUh;_qdCL3naIT{Y~N6G zI@XFo>BIk03jMu8%vkt?-~wif0o~bo(o!tYV^ai~29-?PMuk&nl7C!}nZNU*9Gy$B zjs`&<(5W^_a-)tE+Hq@M=2XJ%7%--3o?v>FsN|#md!gTVlzO#t59rrU?1mr#HVj-{ zT6^h)#bW{4rWjmCY+BZulZI=hNYi&T4Z?-O0XgYS37^z_3EejI9cPUBWV0=7SCdSN z*5~$H>!d*QXRQxVr|I)8MnIAwEqv&}HTPeK0SwpZ0g`seP@l)78>Z1y9j6{sG+^?? zUJ7qLp7*S`C5av87&6o=5su`?|v(vzkhCp_7)cd?H2E8DP z;kvuLUFn5te9C!J$Z~Y}w?9N;kMbZVAD!o9?C7q^6CtGL-m8FeS;K z+c70Olnl6ke~b%qO4w{>!g76cW0H`iJs}!y+lNU7$hRcd<4_bOV@-wa@_wlmBGVvF zF%<_{Ixa&%vMK16yij8gb9YjzYFl~`93dh@#aY1&NuGkW%##{I6&ejJXGBkd@e8Ic zG?9(w*B+ zM~CVmRqq!a_0|a}=PdUjO4lftZvlFlX79EodKFagHQTn2Uq_6%TCimRnQ)DW^L;xV zoEwG=I-3qHVe|Up76?wYJOd&(Zo{6t{oW0GY8=GztC>RT&(unSpV`$oaE<=HJORr(#6*w!^ShLH3Js}S8F_rjH?`w%Jql0144uJ}k!08gK zAj1ej)rC&I2}`UDgC2Mq@+=ce-H7>M&X^hkb@+DmJ%>kM+&qB7)Ch-z4D&|F<*xN; zHVPB&3>L9;x8|HyQs{A|uSRWVP|~Xsi5+zl=&ifIG{lve>&P)$V9cJhzx~w|`**7G zPxSRq5b&Q`@84H9e&Mhyfc#-fzvI7Zd!XjiC#7;dK)t_S_TEdCto-Nk3E zTWv`WHhfqhZZ;-q@cgiP>=`YKfAmF{c6e6c<6;|t57|bQ=*ttkTXBz4u@UswIIt=f z)$etR?ZKZI47mh{N4-i@WQ0TXwDJ(Pu?3!$F@+9T5T~ZDlVGj<`jp91L{OAtU3K}+ zLA>LSrLe5fh#Pp5zwSv8!4$KdBmw()ze5X;)PfH&ZhTDnR0F3!hPCQ*0-CIDQ-bh4 zLacyykyF9R3&~5LrYsdqw977%LAmi0bmZxxngqTIm59B4f&tlV0yGJg5G*S*nneV5 zQ`IwPNbirNqFbv?aB6>gwot$g&Z?OD!Oho$lmBUVeo>8b7-$SqAa%`XrTX@ zaAjmm`qz=34?i=fv%Aqy1{$PE^R!A4@);iJ#e3nZ;HhcW$Is%^WiN&C`8z`5|d zw+!U4V?K+HUypJ{kT8yz{!D0Ktl%f7j+n#1>9*N&r^sw{GV*ZMTa0Y|ph1y5CSXe< zQ2Gh_2`r_b5_flp{$aA;;w^h z=Rb6+*Y1q$k6Fs$m0dF);cfWf`mn z>j3mtz3Nvts=nZ>9PV7Oc^HBy)^yP&(Tz7^tfJ%q@t+K)S9)}^=-ofV<6a|)y1$HV zX&ga&y>VTc&P?4tn0Uc&m@13pMn(>6Q+5|=K%LJ1z0!nKP>yd)Hyp?>6+Wv{Wp4Wv}ZK`C4U;We2WdB2Xyrn zt;|JJBm@=83K5SB%`Aq+k#I$dM(KwH%k+!)E!4CVBF0WHvG;%_!4Y=zvl4iTPGL7I zlEpVL{muNjacmaUhwZsgMTlCz z1J!pX2B97J)}<_rgaypW&>CeFQ8eaQSj%zQZ;Cqwl_Vl4D4RbQr*Ua?FXwiy6=fzJ zKJDzOUKw2FdLhAM3O$TDfNxJMN2z`r+}gs?NzVe*0QM*#pX9TE{`OJGQ&+SF=l+pR zLbYRZX9EpgzYZSnCP%?EzFcyl9Mz;-$SRcZLYrIy`gAthG=5dPh(mN@hIFL5af>oZ zIB{8q@b}5in$+fkZbBw*$CY~BQx*F3&vIE%3OleTvsq$|yB|vC_j)i@6!J%`HMJ2p zPTkCQdWuc4&U}lNH|HAuMT7SH*Q0R!aU$(~Tz!~nuUg|=J8nX=CTzrQ*mpHer1gP5 zL0@+L$3#UAYzk#<(_3zwtf2&2XKs2+I-N2Kt2(~LwZU1l;&@-t@& z1{#mQy_147Z0K5$svmdSFB3axuK$xmD!Ct$=8H(xAmYCevh{WSIH(x{$l zK85y%j7oWC|4RlN6BHr?!nunAW8${rJq@AUahli4=~3^ah7&t!crbKg=<=bTxSZru zLu46d(ui4Mb>dNUln&k6iGJxzluwG7*ZKAG$G(kLaSQUJVseRKcAbCM@~T(1nTc{l z-RAM7fU^$nLAnu1%j!9Ek?(GpFIssJ<;^rDZ|dI4vRdaBezjY zq7QY}IH`^d7wOabb?T-9Qf%DFqy|oN4S5eyF|3TvxQbuF;gmKcQ-fvI6y>8*4Cd>u z4NR?ZYSrW-X8wIu^Up69xvaSS0B>Z4WYmAtoKtnW+wwZZWnTA6Ob$u;{I?CVuNR!_ zMaP^dSMua<)HS%TT78PH%5*mW-Op=Yk-XH2mhnb2xM-_iO65j<<9z3DEyl`jA!lYW z>fV~7E2Yk2$vO{iML9N1eO;WVGJTXR_UqE4#8Sr!ryG*NW^?8kK0e!?2s;*w#Rcf# zEX=o>180c>*(=jg&a(54M9lPa$FC;FwGc;v!fq>9Q_5e1V-l1 z896 z5%MCBE6`L!sBWjVDV5uCJxpNB$NPFLT)p;`6%+2rdx;jqyzew!f+hGBo*OPcIC`h} zg-CVrFBn?8-4-;#Hbus3M)rRz^_e3{-qwC3Nw1lOk1^C-jiLBmKVP)Y`Gz+8Z;m(5kzs#Ynr!be z=R4bUw^vcgU7f&*2s>=(lEDm{qPO*N^~Ho0#t^^L>Rq>A$Aye=2Bj?9yv=J@MmsBH zSw>z{yN0!f;>V0{t9$*kJDYW)WpC2gch1XhsLk^)Vp$B|G9o~u>d?1*5sQPX~_XrHvEo8uiJ(n6rl#4ePg(8;=9?bH3SURu%! zMK!>yg`cyl%k%wjoHD%(Et4=za`$1oy`ax}KS1Xs#lsKoz>b|kuOP%z7~Fop`?z6u zL$U4PwSfNi+i=W?@(>SU%fcq1S>!zl?S~fe8sw~9MTHtA3hlOd=*x zsQx}}zog7KFpYvhe99A@g{h?n|@U=u}>xglfmViHn$gug}UM)k%=PvLNkx6gT8OHtvx^!CZtDm-bA-&3rX&e53p% zYH2NoT!oxuxwp@vVBP$QfPAW6?8^rIVQ5I)p@HZ~0V&n%H$-Bvjq(a*P%Mz2N67${LHEplF7OjP8Tv0@t``uA-E< z&!b+@inq_%pOX*5cxJKfd2N|vucASNMCC~o0pILAI}qLlCk^qG&i4>kRO)mE%cvT-ehLJ7;R(1 zlcgf1;;|s_;1ZvC@8cvR-ba3m6^P`De{)JruFW~kbfv}a(JysawaHi?<%BiglzQ5* z_tvwNlD;C(>S|~Z9nkXpnMH-$)-csR>_T6BFH<(km;* zovq>Oi${DJs@2+QobhaCa8TApM7}mN!iGj!twghrFudB}Dh~Z+ViIja7PjyN(&;nS z@zo#vSL9tT%-r6%5k=f&O%wO(#fycXUbj`7SM{h*b!@r021`{M_jnqu_>)EupJX- z*srGiJKqGCktKc@WjG@;(OrDX4`q)P|<&s*^2&aSm3cl z#YoV-C0Qb4lkx`rOWEH~k4xd8`V(*2+6?L34&ag!k$QthVj$AS9gI%8)vKfNO9yKz z>bzJ;;rV&f% zGu@TeSciy*XjRc(0R3lkrd7nfwq)}fUO1_*WR>xZL;?uKF zIcTJ1aT-_ErLMK6J(SvNvY*mge6Dp3S^ir^?QcvgTbF=UL$hadg2c=O?E)fc_)otp z$5~g0bNq~X{EN)YJH1zGX7i;>u1fU%Pa5xtz?CJeEw}VlG(Hl@a?$6EigkcA@*heW*j-oPC zyuGEL(J1Fzki~YFn*JE+ISzLY^yG#X^H(91=DLgKyk1ReBC0MkXPlg44Ya1HAv`^l ztRXicoAybm*P|F3unfn`@Kq$WxQecqTeW#~{JMUEigL?kje5mHt)1JfEB)+@ZOM)3 zhvH~#O$z?aW^{I*G}7^5bh9CgG}iiFi3%k5v~}|O^PluCZ`~nLE`;z;XJ~tg#L1>t ze7uHjns4qp^kVRu;^vZA0qf=7Nq$eS5Qu|jlik>>drV&81&>VDJ{Ptvwp3bslUJ~E zwY~3sbUG8=Y}BrO^;L{2nO}AZo0geJT0tstt6A0B#)O{L87o9c~A>{YY5`&J(F`%2YdKo3`S!6;|?h|nUh~Wlg^Mm`59kC%si|ra(>y5=5(+? zD094;asY9J>8Z)@%BYhc5zAme@ zm_l(Yy2(2Y4)-JJ7@Nqm9w<9M&nNb3YEsIXal(2}6D}s-peuN+x)%RSV3Jxt{heS9 zmFd@?emiN57_&J715tY&A*_Spz^c~M^{AmGm96|B^aGnZn~=Sc3%II zR#86bjKM@*M43ZzM4rv1Zkxo~&_(sd_fshIj}-}8fBU_Xmg}9cMmbh;p=hYzJ*SN@ z@mWCf+t#OTezlh`OF9aFU1yTjVwEx%4WFL+lG#MtsYKZSL?zO4l<#xB?d$6C=t`sr zuB8G_^tSQ^K7#V}r_C2f>|C6j^8%G7K6@c$h9O5j4bJ6s>~&vwcFRXa_a&#SLGa7l z`54||o78&E636R%`uokF_0zFczEo;|$WDJ1f0!^=+Zo(XGbtK+g74%mcuXgW`g4}t z^b__#=kRM4-H^U%@}$I`(?Z3i;$z;1lLD``QLfYXME6!z*lk3_={)M=;L9YbRnyqY z4B()!F7Na*ajn)3nfDzbCyeD48Mv$T<=A94_A*%rF`tZ@fO+@TV++bFRt0aM(?Ts)$1SQ>h?{%Snk-e%Y)H7S6@7V`wuMTnEn_v* zm8bM>)+vgJfx)-ZJbc5oesjXyXG?rzUt7_TLKImlYPjGWfQ?A>e-MXPeq@gd)C76s!dG*Z? zLV_nN0ewn~aRF6=33k(_d4;@MIYlx2-TmCOq7f4UJ(hBi2LryUKA(Jx-MszJOZ{@O znSHqB_!I7nF1c!eP9vsOVl~K&#K0qFXnRm&J0mL-2hQz$AAHeu|8rX<;4-fTf$xEo zXe7=?1ypoyJ^#+G{6NTtzykB6bXY)%)R1qNcAsjhg;Z?xaMrut2FchD#@ZBn}J&Wy`SN!S5 z*3Al>604Q!g}ygg)@MB(AZLxPl6tn*oqViH+KiH2sL$WcsH*Iottm-hHkD_}&s0QO zSDp6@MVZ3V5+_@K^9ps)Lr!}Q0&6uKn|!S(dhEg5DJbmAGUT;0O`(1pG_u~sGwh$K z>?~W8l;ns%m5!l0v&i1R_P&>vjqx3lq{oHxfei6q2o;#^9KIw6sy7Q`(gcjY*!*?3 z@E2C1wI7FYw3FYL623I_AP)jcFAKHfA0q{(T-5Au5MA?-=E7bHnc$thB7*ZM6}&_Z zkxD-;iCW#6=TLy7W^C~0xdxiYd8hXZlOoQaq}aynex>wty*{lg$K@H_;hwBvQ>5@y zK2V^BCY?fJ#eWL%nG zN&D`vKXhxbIYT`-WNT^?CKNy4jlJbbQAC%f8J*cq=g$Ht9MpQT(@ zIpgoor%M>Cawa!z(yP7it;Lgm?^jM!tlD2&GC2!mxwNjVLfUQ)hu?X`_I@j2Tit(xm&jaf1!Mmb(AR1GM*?tDOUI1K0=5 zBc3Ph9i5>7)vKiWG2qe{4mfF$?E&mObf+8@Y0n?ucTVi27bd(Eo zY~DYqYU^HAa~|msf!fRGkEWUKP{k>tFW`T`m|{U{ecvQvUy?tvz{ClueYw<`aDrL# zTqaBCq(yYpFfIfV;URYR;#sl#gPZfQw0EiG!)IcjHgjAv>UdaGmXwrL1<6+u+uFqLF5VDkg`LGR1`k<)gY z&i}@v2H>%g2RmrND-;i(u{I6uY*_#mB%dlK#c zfI9gpu5Md439kM~yF61g!P-5|=5uK=3%)E5M}sA-B+~S6GBg(Z>BYSRgPS~D*&T4N z-074WWEZ;ixE-@RE*u>@s! zAm;D;rU%ic>3_&qVf{uYG+}=55G@S($JEf)3V+#^4f5s7nSGV&Vn|dZuKvE7L<%~l zO_&c|aULn~^kEZg=iR@Qd)CLxtl{Ufm9v;|%bdt!cc?7u8+9%9a;A4R5;&^5y1usP zOYE)s*RMN=+|zm(#1vcq{bgfbUa$h^XJX@VR|jOgC-myB%xvT~cJQ&#yrEH9 zunbjWjWlihP%Cb>_50U}97qqv`?2fT&wYvSd$#H~M9F+^WRf?R;0m&4bXbo3>{=`@ z7QrSxojO!eYg|la5YHfacOZk8JGFvtsiJ%JPWbPZ9;q_LyxiDP8c$NkQaRlWzRYt5 zy&q^^H%bJR%kX>P&7@4=g~ffT79V%T{BmOkTl6{l>P-Pl1{r_urO3ORthLT48SEGP z8o5s5T>1DewOQatVoP42h5`O7V>H)VLV|%xu2icM{&XDa-b$++j%&yycHWgvtd)`` zI>bT>LM!b;m||0>U1!9%y3-p7(Q_@Zc^?w~2%eVYeBn=`n4-;Jd~xxuK4`ON5~o1BfE=z0;KqTR-VKy-${KwRC4|A(R2 zS;{oh&B(TAR;eW^C1G!c8;*(U%+w4OOSdR_S-v{%ULCb5|B3aS_tKmZbslA?%&QcJ zSW-_xAuz2?Waix(d(zE;aGVQ~#fxq~9bPFndn3&m<)v?pudmx#OXuEg8IivEjp3H( zg|n0PIue$JQ|>80Qrvj1yV!~1B^UWuYQ^=Y_jFEH`I9M8ziH~Me>`QTfvzuH!!I;m zm!W&{`8n}lNh9ou*&p19^zXA-B45!jr|3I%|GDDh+t}9Rr(}4pl6A^AlJ-=e({?Z! z@e&rF88px27jMT1rD=1c{lh z*3xnvtg-RYq{WR)YpjudN~@04p1i2nZ(q3e?kjPc{;RWDlyuqsVfER^MGE}ey*W$V z*Gu`PPP_Ha&=xx4fLQ-PL{E~PptA{#B+eMO%tToonQUaHiH1PKBM~-1Vw|MNtl(Rml{e}=9N05(9PvI0`BOZ8Y8`CI zY-+chemZSVXY3pIB#MT{1%~VX{fT8ljl?}ys6+>ohD8%xJ>7$`rOV!*or{xcztKZF zGanV7BcdPJZ=%=9Jd7OL&E#l1>igO;C~8prxd5Sv|0h#ng}60;-K!ZTWNThuQc{SX zHx*Ssd4C677|EaL&?LQre&cPT%C zCCqIv*}ZXC8Uq;6H%Id7Cp2`gl6_vmZu_F3f?_3lwzaIa+1-vpM=6!chSfw?fv@~L zMawLGstFMV_h;I-hSd4IjtMJqTbyBR()G9TIIrKkt*eo0@)I-EFx8l+pKWf^q>U)=puZ)UTOD~em>@f8J58! zTw6WpmYHlhjS>d-k#X=N*^9Z3Mh*t{CjW6WxjO>gOyod`nU;>l`lMZ;U%@l0$V&>7 zpeV_g|_%;W81tu&lq{6xEu6{Q3#Y_fwbKa3l!t zn9+5S-+M(t61Zu!SC#OFI@!|$xo>m?n=P(~ zPHzNVTcs!VIhVb!skJuVT^c{YR~z_2yU708Ps~hgO&koY|08n|Z=uY|e%vHVrDLgB zAB(=Ucuq!&^#OanMJrRf&$)igp3OK%DF;`c^X`#}k6tpk)Qgs}<|rFN&LhdoC4ikW zP3fEr>&IhsLlVLI*ybK5QC@(jbPw&vQ(zB^u0 z$N#ac+^ZnWhw|ONy?@rBK2-wnBMW}eJrbc&x2uWazuI);v^C)0qQOS4-&z@a6LhKZ zl^Z!jh{9^s0;f`0dOMM!ttLZYKY>8FkpF^YiNehHN7rz2E^SCq)O`^#aTc+=xwm7} ztNQEQ&0N-@0S6a;P;dOxeaXQ|4GK)r#Z7Mx-sw6TkhHT-a;yxt`VeMZkDyqng_z%(Fq^s z{6dCM-sN0K_a#k74~s>XYP8#m>On>7phjJP;kH4<^xmGwSCF%a47)D8nM}-dUH9R0 zj1wVg6v5o0LiThP7#N}CB>`eo;bz~t-A%0$Hq%HnUkO^K2%02voxZNz9Jh$PL~ud+ z{OCIWeWFnG*&E*!QxeBr=wp|B+7yVULx=o7obr#G&F(8Ek2PeJieT)~XRz10gsWsO z9cXf0VdA!nNLWD$z4fD-GyM+|Y0zF&JBf-){BjJ#iS}{0?t#0~-u3#4|FK_R?zvXz zNuYk?S{)j&$+|}#P{o_L;xEBbSktX49;|4Uz0ske8=FZ$*&Isz(d%GrSh7ss zN&<6vhWQ1D*tPNIfkgktM?`8Bat6y2>))2^R3g+EOV}PLb@XZ8Er~8Hs9t&d%gSH= zyIA{(7&!yFMa?bobLhi-NT(9-k5qIi(+vE$T8u)8(m`G|LG(1BCK{_r4klF)yGMJ?!w0R@7@ zwsPQO7(Ck7eQ3A{Xi{)!P6m!v&^qIU*4wJ6k6QJ8Nqb2ShThYe#4RMh05> zs4g79^#uXs6<9eUFH}VP$?Sf+N8klo6xsKU2wu(m&y{4mYKE$06(|Xj7d>!|%EC!c zZ$}@{L*k+Edpsb2c~g=HRLl*;wF3{+xB^f=BD}qYy@|Djt;r7jk*kNnL%-*6&ER~o z2Dci$a1Ou&13-k|{(ly>W;^hQ%!PngG*km}J=OM60DcJ%0--=qG{&g|@CGg>h${Za z`n9V9bY?W?Z1kXWZ-7D(9b%DwKLL9K2giLB+R=}&Raj6E(ey`Xl|ZzsUuaNx%(h3t z!2~=^GcvLHbNvqZS_I~S{Rmz zcT8Xpb-&*p+FxUDFM&E15XSD`iCti**>DT)0o&Lan^^w||3|tL%og{@8uDFG=xW^# zg6?1RKY~qhk-tvc;6t8IVA&6V8WFvz;~@U_)j;T*$K7}{_Vll|h-2@iBkud#$Qaln zHt<<|1T7*7?}-ImKr#DMkO7`#F@H!m6R5OdVa&J$Tx&rU_oYOFKny^nM}#dB*@Jbq z&;!Uj)^X?e5wU$Q__jGu&d`9C;2yLP2sOfL$;9_ycela4t!jtHKOz{Bw!h9o#?_a% zfn8gG2#jdgk#c)9oSiJJ9d}SMaQ`Z2-%Kx^Jj=B=>p+u%K$D25hKhTrj^I+~F6x*v z`{A1r%>MSjr6t(4zwKD4w1>L)Sadr=9r~hnPkm5aOo~a>F|blCAP0H`IWHZGYhVqw zIdIn*?)fgTlm9@7dy;R%7>LCc{OAw}@u(cefRVL{fvvOs|3qg^Dp1GiGG}->u*C_m ziIO1DS%jkl^Pug+Fs%9rm=?~IOffJgKnHjEiuY{*R04j8Mw6wx2aMqIgY$oNBB*k0wV&9F1I1nhsU0DLEZncd zp&B_@*gJvK^UivY)aK#g5c3Z*bmeoB$VLzdG?BaEY~pMJ%dYVL;igIgqg&VV0$89c3vg?4B+el z--zk=+dVLu?JugP7GO@qpNx4s@EvIwd+_?78nTfAbP)IVveuw@fRCz#&4WjOz41pCu3L?bW)P#_C1bpHRPU3=Re)O|Dd!2Ub} zBNK3#cGrV;352$11DnqIrN2T(qdXpQsLjF@*j8!n4O21fe~}I4Ew2^$o?x8zFjK+ftMocYm7-Cvtm4; zm#&(>QsMotRPdz(b%GyEHv5Ak+Z;H2V<2e1r2_&{m6epaD7!sp82D?^-!oXKzama7 zhBv109>}5divjLGHV|mkM;vAfkK5J{8Z5$%HU)S`p0^Koe#GR8Yha)AZ*QNwB0X}g zFzkaPNa5F753peaNx>=)8Ab|Ufjl@>5rzcwd*NY_VDHRW1Yn1bM%=4g><7d8qiGnJ z+a4Hf-s0Z?VSFB(wg}H>Eh6CF6a~rgcK7c-C5E1-= z@ZjVYc1)(2Ye!cd_njSOE8P-^+(XI!vG zya4eZMM7vCg#On%e~8Xj4-nz{>26!XKY|Jr5V0jMJmV-E2!J~^tDOw+AJ_-`)WTyc zZEj=lU_raq{za7gTZ`;uldvdb2987f3P{lQB7ec#Uzpkn)KI}@_~szsA+~%2N;|6)CZNVe+qr)S^ z_1*%&hxFZoU-H5JQ1HNm81TSw-J$^SA)TV&fe&^rf(L$p1rLnS#|S_l(!&S_4RhT6 z*0xiDf?3-HxXig{ZM&fcmK7gqcQD&H*whAo(fqiFBk$7q^B4_qa7cR_c;OsuKmt!^ z0q<}++qFf6b|iq(A+1Q@Wp%K>1dI|)RvsteDZxD#-40IBZWD((DNI-gdriPI(Rvj0 z{>~GCheNtf!1HjhZNd%@&}d*rbOaCE;(}|U00 List[str]: + volumes = [] + for name in os.listdir(book_base): + if name.lower().startswith("volume_"): + full = os.path.join(book_base, name) + if os.path.isdir(full): + volumes.append(name) + volumes.sort() + return volumes + + +# ------------------------------------------------------------ +# Celery task +# ------------------------------------------------------------ +@celery_app.task(bind=True, queue="m4b", ignore_result=True) +@logcall +def run_m4btool(self, book_idx: str): + + log(f"[M4B] START book_idx={book_idx}") + + book = fetch_book(book_idx) + if not book: + log(f"[M4B] Book not found in SQL: book_idx={book_idx}") + return + + title = book.get("title", book_idx) + author = book.get("author", "Unknown") + + output_root = os.getenv("BOOKSCRAPER_OUTPUT_DIR", "output") + book_base = os.path.join(output_root, title) + + log(f"[M4B] Book base directory: {book_base}") + + if not os.path.isdir(book_base): + log(f"[M4B] Book directory missing: {book_base}") + return + + volumes = detect_volumes(book_base) + if not volumes: + log(f"[M4B] No volumes found for book_idx={book_idx}") + return + + log(f"[M4B] Volumes detected: {volumes}") + + # -------------------------------------------------------- + # Build canonical commands via scriptgen + # -------------------------------------------------------- + merge_block = build_merge_block( + title, author, [(i + 1, v) for i, v in enumerate(volumes)] + ) + commands = [c.strip() for c in merge_block.split("&&") if c.strip()] + + for volume, cmd in zip(volumes, commands): + audio_dir = os.path.join(book_base, volume, "Audio") + if not os.path.isdir(audio_dir): + log(f"[M4B] SKIP {volume}: no Audio directory") + continue + + log(f"[M4B] Running for volume={volume}") + log(f"[M4B] CMD: {cmd}") + + try: + result = subprocess.run( + cmd, + cwd=book_base, + shell=True, + capture_output=True, + text=True, + check=True, + ) + + if result.stdout: + log(f"[M4B][STDOUT] {result.stdout}") + + except subprocess.CalledProcessError as exc: + log(f"[M4B][FAILED] volume={volume}") + + if exc.stdout: + log(f"[M4B][STDOUT] {exc.stdout}") + if exc.stderr: + log(f"[M4B][STDERR] {exc.stderr}") + + store_m4b_error( + book_idx=book_idx, + volume=volume, + error_text=exc.stderr or str(exc), + ) + continue + + except Exception as exc: + log(f"[M4B][UNEXPECTED ERROR] volume={volume}: {exc}") + + store_m4b_error( + book_idx=book_idx, + volume=volume, + error_text=str(exc), + ) + continue + + log(f"[M4B] FINISHED book_idx={book_idx}") + + +# ------------------------------------------------------------ +# Orchestration helper (UNCHANGED) +# ------------------------------------------------------------ +@logcall +def queue_m4b_for_book(book_idx: str): + log(f"[M4B] Queuing m4b-tool for book_idx={book_idx}") + celery_app.send_task( + "scraper.tasks.m4b_tasks.run_m4btool", + args=[book_idx], + queue="m4b", + ) diff --git a/bookscraper/scraper/tasks/statuscheck.py b/bookscraper/scraper/tasks/statuscheck.py new file mode 100644 index 0000000..51be307 --- /dev/null +++ b/bookscraper/scraper/tasks/statuscheck.py @@ -0,0 +1,149 @@ +# ============================================================ +# File: scraper/tasks/statuscheck.py +# Purpose: +# Final status check after audio completion. +# +# Responsibilities: +# - Verify Redis counters (sanity check) +# - Verify filesystem (Audio files present) +# - Queue m4btool task +# +# Design rules: +# - Book-scope ONLY +# - No direct Redis usage +# - Repository is the single source of truth +# - Idempotent, defensive, non-blocking +# ============================================================ + +import os +from celery_app import celery_app +from logbus.publisher import log + +from scraper.logger_decorators import logcall + +from db.repository import ( + get_audio_done, + get_chapters_total, + set_status, + fetch_book, +) + +from scraper.tasks.m4b_tasks import run_m4btool + + +# ------------------------------------------------------------ +# Helpers +# ------------------------------------------------------------ +@log +def _detect_volumes(book_base: str): + """ + Return sorted list of Volume_XXX directories. + """ + vols = [] + for name in os.listdir(book_base): + if name.lower().startswith("volume_"): + full = os.path.join(book_base, name) + if os.path.isdir(full): + vols.append(name) + vols.sort() + return vols + + +@logcall +def _count_audio_files(audio_dir: str) -> int: + """ + Count .m4b files in an Audio directory. + """ + if not os.path.isdir(audio_dir): + return 0 + return len([f for f in os.listdir(audio_dir) if f.lower().endswith(".m4b")]) + + +# ------------------------------------------------------------ +# Celery task +# ------------------------------------------------------------ +@celery_app.task(bind=True, queue="controller", ignore_result=True) +@logcall +def run_statuscheck(self, book_idx: str): + """ + Final statuscheck before m4btool execution. + + Triggered exactly once by audio_completion quickcheck. + """ + + log(f"[STATUSCHECK] START book={book_idx}") + + # -------------------------------------------------------- + # 1. Redis sanity check (via repository) + # -------------------------------------------------------- + audio_done = get_audio_done(book_idx) + chapters_total = get_chapters_total(book_idx) + + log( + f"[STATUSCHECK] Counters book={book_idx} " + f"audio_done={audio_done} chapters_total={chapters_total}" + ) + + if chapters_total <= 0: + log(f"[STATUSCHECK] No chapters_total → abort") + return + + if audio_done < chapters_total: + # Defensive: should not happen, but never assume + log( + f"[STATUSCHECK] Audio not complete yet " + f"({audio_done}/{chapters_total}) → abort" + ) + return + + # -------------------------------------------------------- + # 2. Fetch book metadata (for paths & m4b meta) + # -------------------------------------------------------- + book = fetch_book(book_idx) + if not book: + log(f"[STATUSCHECK] Book not found in DB: {book_idx}") + return + + title = book.get("title") or book_idx + author = book.get("author") or "Unknown" + + # Base output directory + root = os.getenv("BOOKSCRAPER_OUTPUT_DIR", "output") + book_base = os.path.join(root, title) + + if not os.path.isdir(book_base): + log(f"[STATUSCHECK] Book directory missing: {book_base}") + return + + # -------------------------------------------------------- + # 3. Filesystem validation (light, non-blocking) + # -------------------------------------------------------- + volumes = _detect_volumes(book_base) + + if not volumes: + log(f"[STATUSCHECK] No volumes found for {book_idx}") + # Still allow m4btool to decide (it will no-op) + else: + for vol in volumes: + audio_dir = os.path.join(book_base, vol, "Audio") + count = _count_audio_files(audio_dir) + + log(f"[STATUSCHECK] {vol}: " f"{count} audio files detected") + + # -------------------------------------------------------- + # 4. Queue m4btool (final pipeline step) + # -------------------------------------------------------- + log(f"[STATUSCHECK] Queue m4btool for book={book_idx}") + + set_status(book_idx, "m4b_running") + + run_m4btool.delay( + book_idx=book_idx, + book_base=book_base, + meta={ + "title": title, + "author": author, + }, + ) + + log(f"[STATUSCHECK] DONE book={book_idx}") diff --git a/bookscraper/tools/mp4info b/bookscraper/tools/mp4info new file mode 100644 index 0000000..86b2f30 --- /dev/null +++ b/bookscraper/tools/mp4info @@ -0,0 +1,13 @@ +#!/bin/sh +# mp4info shim for m4b-tool (ffprobe-based) + +if [ -z "$1" ]; then + echo "Usage: mp4info " >&2 + exit 1 +fi + +# ffprobe outputs float seconds; m4b-tool expects an integer +ffprobe -v error \ + -show_entries format=duration \ + -of default=noprint_wrappers=1:nokey=1 \ + "$1" | awk '{ printf "%d\n", ($1 + 0.5) }'