Advertisement
This is comment for paste
Untitled
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- # Original: <https://pastebin.com/xsUhLTtH>
- """
- Moves a recording file when filename matches match_keyword X to output_folder Y
- Created by `Sateviss` :chatting:
- Refactored and cleaned by `JohnSmith`
- """
- import logging
- from pathlib import Path
- from time import sleep
- from typing import NamedTuple
- import obspython as obs
- # Configuration constants
- NUM_OF_MATCHES = 4
- """Number of match strings to be configurable in OBS"""
- NUM_OF_POLL_TRIES = 15
- """Num of polls to try between OBS signal and moving the file."""
- POLL_WAIT_TIME = 1
- """Seconds to wait between each file poll."""
- LOG_FORMAT = "%(asctime)s | %(name)s | %(levelname)s | %(message)s"
- """Logging format for the script."""
- LOG_LEVEL = logging.INFO
- """Logging level for stdout."""
- LOG_FILEPATH = Path.home() / "obs_recording_migration_script.log"
- """Logging file path for the script."""
- # Data classes
- class RecordingMatchCase(NamedTuple):
- """Entry type to encode a match case for recording migration."""
- match_keyword: str
- """Keyword to match against the recording filename."""
- output_folder: Path
- """Output folder to move the recording file to."""
- # Initialisation functions
- def init_logger() -> logging.Logger:
- """Initialises a logger object for the script."""
- print("Initialising logger object...")
- # Setup logging to stdout
- logging.basicConfig(level=LOG_LEVEL, format=LOG_FORMAT)
- logger = logging.getLogger(__name__)
- # Setup logging to logfile
- file_handler = logging.FileHandler(LOG_FILEPATH)
- file_handler.setFormatter(logging.Formatter(LOG_FORMAT))
- # Join logging handlers together
- logger.addHandler(file_handler)
- logger.info(f"Logger initialized! {LOG_FILEPATH=}")
- return logger
- # Global mutable variables
- script_logger = init_logger()
- """Logger object for the script."""
- recording_migrate_mappings: set[RecordingMatchCase] = set()
- """Mapping of match strings to output paths."""
- # ================================
- # OBS invocation hooks
- # ================================
- def script_description() -> str:
- """Return the plugin description string."""
- # Just re-using the script docstring; see top of file
- return __doc__ if __doc__ is not None else ""
- def script_load(settings) -> None:
- """Initialises hook for stop recording signal during plugin load."""
- script_logger.debug("Attaching handler...")
- try:
- obs_frontend = obs.obs_frontend_get_recording_output()
- signal_handler = obs.obs_output_get_signal_handler(obs_frontend)
- obs.signal_handler_connect(signal_handler, "stop", signal_handler_function)
- except Exception as err:
- script_logger.error(f"Error occurred during handler attachment: {err}")
- raise err
- script_logger.info("Script handler hook was successfully attached!")
- def script_properties():
- """Hook to setup initial OBS properties for the script."""
- script_logger.info("Setting up OBS properties...")
- # global NUM_OF_MATCHES
- props = obs.obs_properties_create()
- for i in range(NUM_OF_MATCHES):
- obs.obs_properties_add_text(
- props, f"match{i}", f"Match {i + 1}", obs.OBS_TEXT_DEFAULT
- )
- obs.obs_properties_add_path(
- props, f"path{i}", f"Path {i + 1}", obs.OBS_PATH_DIRECTORY, None, None
- )
- return props
- def script_update(settings) -> None:
- """Hook to update recording patterns"""
- # global NUM_OF_MATCHES
- global recording_migrate_mappings
- for i in range(NUM_OF_MATCHES):
- new_match_entry = RecordingMatchCase(
- match_keyword=obs.obs_data_get_string(settings, f"match{i}"),
- output_folder=Path(obs.obs_data_get_string(settings, f"path{i}")),
- )
- recording_migrate_mappings.add(new_match_entry)
- script_logger.debug(f"Loaded matcher {i}:", new_match_entry)
- def signal_handler_function(calldata) -> None:
- """Handles the recording stop signal and moves the file accordingly."""
- # global recording_migrate_mappings
- script_logger.info("Handler triggered! Running recording migration hook...")
- try:
- # Get the last recording file path
- orig_recording_raw: str = obs.obs_frontend_get_last_recording()
- if not orig_recording_raw:
- script_logger.error(
- f"No recording file path was returned by OBS: {orig_recording_raw=}",
- )
- return
- orig_recording: Path = Path(orig_recording_raw)
- script_logger.debug(f"Recording file path: {orig_recording=}")
- # Wait for the file to be fully available
- for poll_i in range(NUM_OF_POLL_TRIES):
- sleep(POLL_WAIT_TIME)
- if orig_recording.exists():
- break
- script_logger.debug(f"Recording file not found yet: {poll_i=}")
- else:
- script_logger.error(f"Recording file cannot be found: {orig_recording=}")
- # TODO: turn these returns into error raises?
- return
- script_logger.info(f"Valid initial recording file given! {orig_recording=}")
- script_logger.debug("Trying to match file...")
- # Find matching file migration mapping
- for mapping in recording_migrate_mappings:
- # Checking if the current match is valid...
- if mapping.match_keyword.casefold() not in orig_recording.name.casefold():
- script_logger.debug(f"Not a match! {mapping=}")
- continue
- script_logger.info(f"Suitable match found: matcher={mapping}")
- # Checking if the matching output folder is currently valid
- # NOTE: if this gets race conditioned somehow, just throw everything below into a retry loop
- if not mapping.output_folder.exists():
- script_logger.error(
- f"Output path does not exist: {mapping.output_folder=}"
- )
- break
- if not mapping.output_folder.is_dir():
- script_logger.error(
- f"Output Path is not actually a directory: {mapping.output_folder=}"
- )
- break
- # Constructing the new recording path
- new_recording_path = mapping.output_folder / orig_recording.name
- script_logger.debug(
- f"Valid resulting recording path constructed: {new_recording_path}"
- )
- script_logger.debug("Attempting file migration...")
- orig_recording.rename(new_recording_path)
- script_logger.info(
- f"Recording file has been migrated to: {new_recording_path}"
- )
- break
- else:
- script_logger.error(
- f"No keyword match found for recording: {orig_recording}"
- )
- except Exception as err:
- script_logger.error(f"Error occurred during file migration hook: {err}")
- # TODO: should error messages be chained up to OBS itself?
- # raise err
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement