iamkroot / trakt-scrobbler

Scrobbler for trakt.tv that supports VLC, Plex, MPC-HC, and MPV.
https://github.com/iamkroot/trakt-scrobbler/wiki
GNU General Public License v2.0
449 stars 30 forks source link

[BUG] Empty remap_rules.toml breaks init and vlc #310

Closed JWWolstenholme closed 1 month ago

JWWolstenholme commented 2 months ago

Describe the bug

If you have created a remap_rules.toml file and you leave it completely blank or full of exclusively commented lines, vlc scrobbling will no longer work and trakts init will error. Probably other errors as well.

According to this issue, an empty toml file is still valid.

Desktop (please complete the following information):

To Reproduce

Steps to reproduce the behavior:

  1. Delete all content of the remap_rules.toml file (or comment all lines).
  2. trakts start --restart
  3. trakts init or trakts test vlc -vvv
  4. See error in console (nothing in log file)

Console output

Click to see console output

``` C:\Users\redacted>trakts init This will guide you through the setup of the scrobbler. If you wish to quit at any point, press Ctrl+C or Cmd+C ValidationError 1 validation error for RemapFile rules Field required [type=missing, input_value={}, input_type=dict] For further information visit https://errors.pydantic.dev/2.8/v/missing at pipx\venvs\trakt-scrobbler\Lib\site-packages\pydantic\main.py:568 in model_validate 564│ The validated model instance. 565│ """ 566│ # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 567│ __tracebackhide__ = True → 568│ return cls.__pydantic_validator__.validate_python( 569│ obj, strict=strict, from_attributes=from_attributes, context=context 570│ ) 571│ 572│ @classmethod C:\Users\redacted>trakts test vlc -vvv Stack trace: 12 pipx\venvs\trakt-scrobbler\Lib\site-packages\clikit\console_application.py:131 in run 129│ parsed_args = resolved_command.args 130│ → 131│ status_code = command.handle(parsed_args, io) 132│ except KeyboardInterrupt: 133│ status_code = 1 11 pipx\venvs\trakt-scrobbler\Lib\site-packages\clikit\api\command\command.py:120 in handle 118│ def handle(self, args, io): # type: (Args, IO) -> int 119│ try: → 120│ status_code = self._do_handle(args, io) 121│ except KeyboardInterrupt: 122│ if io.is_debug(): 10 pipx\venvs\trakt-scrobbler\Lib\site-packages\clikit\api\command\command.py:171 in _do_handle 169│ handler_method = self._config.handler_method 170│ → 171│ return getattr(handler, handler_method)(args, io, self) 172│ 173│ def __repr__(self): # type: () -> str 9 pipx\venvs\trakt-scrobbler\Lib\site-packages\cleo\commands\command.py:92 in wrap_handle 90│ self._command = command 91│ → 92│ return self.handle() 93│ 94│ def handle(self): # type: () -> Optional[int] 8 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\commands\test.py:112 in handle 110│ def handle(self): 111│ try: → 112│ return self._handle() 113│ except SystemExit as e: 114│ if not self.io.is_debug(): 7 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\commands\test.py:87 in _handle 85│ def _handle(self): 86│ name = self.argument("player") → 87│ Mon = self.get_monitor(name) 88│ 89│ self.add_log_handler() 6 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\commands\test.py:20 in get_monitor 18│ import confuse 19│ from trakt_scrobbler import config → 20│ from trakt_scrobbler.player_monitors import collect_monitors 21│ all_monitors = collect_monitors() 22│ monitors = {Mon.name: Mon for Mon in all_monitors if isinstance(Mon.name, str)} 5 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\player_monitors\__init__.py:4 in 2│ from pathlib import Path 3│ from importlib import import_module → 4│ from .monitor import Monitor 5│ 6│ 4 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\player_monitors\monitor.py:8 in 6│ import requests 7│ from trakt_scrobbler import config, logger → 8│ from trakt_scrobbler.file_info import get_media_info 9│ from trakt_scrobbler.notifier import notify 10│ from trakt_scrobbler.utils import AutoloadError, ResumableTimer 3 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\file_info.py:9 in 7│ import guessit 8│ from trakt_scrobbler import config, logger → 9│ from trakt_scrobbler.mediainfo_remap import apply_remap_rules 10│ from trakt_scrobbler.utils import RegexPat, cleanup_encoding, is_url 11│ from urlmatch import BadMatchPattern, urlmatch 2 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\mediainfo_remap.py:301 in 299│ 300│ → 301│ rules = read_file(REMAP_FILE_PATH) 302│ if rules: 303│ logger.debug(f"Read {len(rules)} remap {pluralize(len(rules), 'rule')} from {REMAP_FILE_PATH}") 1 pipx\venvs\trakt-scrobbler\Lib\site-packages\trakt_scrobbler\mediainfo_remap.py:298 in read_file 296│ logger.exception(f"Invalid TOML in remap_rules file at {file}. Ignoring.") 297│ return [] → 298│ return RemapFile.model_validate(data).rules 299│ 300│ ValidationError 1 validation error for RemapFile rules Field required [type=missing, input_value={}, input_type=dict] For further information visit https://errors.pydantic.dev/2.8/v/missing at pipx\venvs\trakt-scrobbler\Lib\site-packages\pydantic\main.py:568 in model_validate 564│ The validated model instance. 565│ """ 566│ # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 567│ __tracebackhide__ = True → 568│ return cls.__pydantic_validator__.validate_python( 569│ obj, strict=strict, from_attributes=from_attributes, context=context 570│ ) 571│ 572│ @classmethod ```

iamkroot commented 1 month ago

This one is a gray area. While an empty file is indeed a valid TOML, it is not a valid remap rules file (today). We require that there be at least an empty [[rules]] section.

But I agree that this is a pretty arbitrary restriction since we allow empty rules anyway. Fixed in latest commit.