controller.helper.verse_interruptor

File:

EuljiroWorship/controller/helper/verse_interruptor.py

Author:

Benjamin Jaedon Choi - https://github.com/saintbenjamin

Affiliated Church:

The Eulji-ro Presbyterian Church [대한예수교장로회(통합) 을지로교회]

Address:

The Eulji-ro Presbyterian Church, 24-10, Eulji-ro 20-gil, Jung-gu, Seoul 04549, South Korea

Telephone:

+82-2-2266-3070

E-mail:

euljirochurch [at] G.M.A.I.L. (replace [at] with @ and G.M.A.I.L as you understood.)

License:

MIT License with Attribution Requirement (see LICENSE file for details); Copyright (c) 2025 The Eulji-ro Presbyterian Church.

Watches core.config.paths.VERSE_FILE and converts it into slide JSON written to core.config.paths.SLIDE_FILE for real-time display by the slide controller.

This module runs as a small background helper process. It uses watchdog to monitor the project base directory for changes to the core.config.paths.VERSE_FILE, then parses the content into one or more slide dictionaries.

Key behaviors:

  • If the last line looks like a structured Bible reference header, it generates per-verse slides with wrapped lines (textwrap.wrap) and style “verse”.

  • Otherwise, it treats the file as a free-form emergency message and generates style “lyrics” slides grouped by up to 2 lines (or by character budget).

  • Before overwriting the slide file, it may create a backup at core.config.paths.SLIDE_BACKUP_FILE (only if the backup file does not already exist).

controller.helper.verse_interruptor.parse_verse_output(file_path, max_chars=60)[source]

Parse file_path into a list of slide dictionaries.

The input file is interpreted as:

  • Structured mode: If the last line matches one of the expected header forms (e.g., <book> <chapter>장 ..., <book> <chapter>:<verse>, ...), the earlier lines are treated as verse body lines. Each verse line is wrapped to max_chars and converted into style “verse” slides.

  • Fallback mode: If no header pattern matches, the entire file is treated as a free-form emergency message. Non-empty lines are grouped into slides (up to 2 lines per slide or until the approximate character budget is met) using style “lyrics” and a fixed church caption.

Note

  • This function does not validate that the file is a real Bible reference. It only checks header patterns and then formats accordingly.

  • The caption format in structured mode follows the current implementation (e.g., <book> <chapter>장 <verse>절).

Parameters:
Returns:

List of slide dictionaries. Each slide dict contains:

  • ”style”: “verse” (structured) or “lyrics” (fallback)

  • ”caption”: caption string

  • ”headline”: display text (possibly multi-line in fallback mode)

Return type:

list[dict]

controller.helper.verse_interruptor.backup_slide_if_not_emergency()[source]

Create a backup copy of the current slide JSON file if no backup exists yet.

This function writes core.config.paths.SLIDE_BACKUP_FILE only when that file does not already exist. The source is core.config.paths.SLIDE_FILE if it exists and can be read.

The backup is intended to support restoration after an emergency subtitle session ends. The current implementation skips backup if the loaded slides contain any slide whose “style” equals “verse_interrupt”.

Returns:

None

controller.helper.verse_interruptor.save_slides(slides, path)[source]

Save a list of slide dictionaries to a JSON file.

Parameters:
Returns:

None

class controller.helper.verse_interruptor.VerseFileHandler(*args, **kwargs)[source]

Bases: FileSystemEventHandler

Watchdog event handler for updates to core.config.paths.VERSE_FILE.

This handler listens for filesystem modification events and, when the target file is modified, parses it into slides and writes the resulting JSON to core.config.paths.SLIDE_FILE. If slides are generated, it attempts to create a backup via controller.helper.verse_interruptor.backup_slide_if_not_emergency() before overwriting the slide file.

Parameters:
  • args (Any)

  • kwargs (Any)

Return type:

Any

on_modified(event)[source]

Handle watchdog “modified” events for core.config.paths.VERSE_FILE.

If the modified path matches the target core.config.paths.VERSE_FILE, this callback:

  1. Parses core.config.paths.VERSE_FILE into slide dictionaries.

  2. If any slides were produced:

  3. Otherwise logs that no slides were generated.

Parameters:

event (FileSystemEvent) –

Watchdog event object describing the filesystem change.

Returns:

None

controller.helper.verse_interruptor.start_interruptor()[source]

Start the watchdog observer loop for core.config.paths.VERSE_FILE.

This sets up an Observer to watch core.config.paths.BASE_DIR (non-recursive) and uses controller.helper.verse_interruptor.VerseFileHandler to react to modifications. The function then blocks the main thread in a sleep loop until interrupted (Ctrl+C).

Returns:

None