Compare commits

..

No commits in common. "1dd6992129bace52b22ad83b6d267c3c4018b0d5" and "34fbc77182d2c84cb3acdefdad1e0032e3b94ef5" have entirely different histories.

5 changed files with 46 additions and 70 deletions

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2025-present onyx-and-iris <code@onyxandiris.online> # SPDX-FileCopyrightText: 2025-present onyx-and-iris <code@onyxandiris.online>
# #
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
__version__ = "0.10.5" __version__ = "0.10.3"

View File

@ -1,9 +1,11 @@
"""Command line interface for the OBS WebSocket API.""" """Command line interface for the OBS WebSocket API."""
from typing import Annotated from pathlib import Path
from typing import Annotated, Optional
import obsws_python as obsws import obsws_python as obsws
import typer import typer
from pydantic_settings import BaseSettings, SettingsConfigDict
from . import ( from . import (
group, group,
@ -14,13 +16,31 @@ from . import (
scene, scene,
scenecollection, scenecollection,
sceneitem, sceneitem,
settings,
stream, stream,
studiomode, studiomode,
virtualcam, virtualcam,
) )
from .alias import AliasGroup from .alias import AliasGroup
class Settings(BaseSettings):
"""Settings for the OBS WebSocket client."""
model_config = SettingsConfigDict(
env_file=(
'.env',
Path.home() / '.config' / 'obsws-cli' / 'obsws.env',
),
env_file_encoding='utf-8',
env_prefix='OBS_',
)
HOST: str = 'localhost'
PORT: int = 4455
PASSWORD: str = '' # No password by default
TIMEOUT: int = 5 # Timeout for requests in seconds
app = typer.Typer(cls=AliasGroup) app = typer.Typer(cls=AliasGroup)
for module in ( for module in (
group, group,
@ -41,26 +61,31 @@ for module in (
@app.callback() @app.callback()
def main( def main(
ctx: typer.Context, ctx: typer.Context,
host: Annotated[ host: Annotated[Optional[str], typer.Option(help='WebSocket host')] = None,
str, port: Annotated[Optional[int], typer.Option(help='WebSocket port')] = None,
typer.Option( password: Annotated[Optional[str], typer.Option(help='WebSocket password')] = None,
envvar='OBS_HOST', help='WebSocket host', show_default='localhost' timeout: Annotated[Optional[int], typer.Option(help='WebSocket timeout')] = None,
),
] = settings.get('HOST'),
port: Annotated[
int, typer.Option(envvar='OBS_PORT', help='WebSocket port', show_default=4455)
] = settings.get('PORT'),
password: Annotated[
str,
typer.Option(envvar='OBS_PASSWORD', help='WebSocket password', show_default=''),
] = settings.get('PASSWORD'),
timeout: Annotated[
int,
typer.Option(envvar='OBS_TIMEOUT', help='WebSocket timeout', show_default=5),
] = settings.get('TIMEOUT'),
): ):
"""obsws_cli is a command line interface for the OBS WebSocket API.""" """obsws_cli is a command line interface for the OBS WebSocket API."""
ctx.obj = ctx.with_resource(obsws.ReqClient(**ctx.params)) settings = Settings()
# Allow overriding settings with command line options
if host:
settings.HOST = host
if port:
settings.PORT = port
if password:
settings.PASSWORD = password
if timeout:
settings.TIMEOUT = timeout
ctx.obj = ctx.with_resource(
obsws.ReqClient(
host=settings.HOST,
port=settings.PORT,
password=settings.PASSWORD,
timeout=settings.TIMEOUT,
)
)
@app.command() @app.command()

View File

@ -65,7 +65,5 @@ def switch(
if preview: if preview:
ctx.obj.set_current_preview_scene(scene_name) ctx.obj.set_current_preview_scene(scene_name)
typer.echo(f'Switched to preview scene: {scene_name}')
else: else:
ctx.obj.set_current_program_scene(scene_name) ctx.obj.set_current_program_scene(scene_name)
typer.echo(f'Switched to program scene: {scene_name}')

View File

@ -1,31 +0,0 @@
"""module for settings management."""
from pathlib import Path
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Settings for the OBS WebSocket client."""
model_config = SettingsConfigDict(
env_file=(
'.env',
Path.home() / '.config' / 'obsws-cli' / 'obsws.env',
),
env_file_encoding='utf-8',
env_prefix='OBS_',
)
HOST: str = 'localhost'
PORT: int = 4455
PASSWORD: str = '' # No password by default
TIMEOUT: int = 5 # Timeout for requests in seconds
_settings = Settings().model_dump()
def get(key: str) -> str:
"""Get a setting by key."""
return _settings.get(key)

View File

@ -20,19 +20,3 @@ def test_scene_current():
result = runner.invoke(app, ['scene', 'current']) result = runner.invoke(app, ['scene', 'current'])
assert result.exit_code == 0 assert result.exit_code == 0
assert 'pytest' in result.stdout assert 'pytest' in result.stdout
def test_scene_switch():
"""Test the scene switch command."""
result = runner.invoke(app, ['studiomode', 'status'])
assert result.exit_code == 0
enabled = 'Studio mode is enabled.' in result.stdout
if enabled:
result = runner.invoke(app, ['scene', 'switch', 'pytest', '--preview'])
assert result.exit_code == 0
assert 'Switched to preview scene: pytest' in result.stdout
else:
result = runner.invoke(app, ['scene', 'switch', 'pytest'])
assert result.exit_code == 0
assert 'Switched to program scene: pytest' in result.stdout