Skip to content

v3.4.0 Code Refactor and Remove Readarr#104

Merged
toddrob99 merged 23 commits intomainfrom
beta
Apr 8, 2026
Merged

v3.4.0 Code Refactor and Remove Readarr#104
toddrob99 merged 23 commits intomainfrom
beta

Conversation

@toddrob99
Copy link
Copy Markdown
Owner

@toddrob99 toddrob99 commented Apr 7, 2026

Finally merging in #100 from @jordanella, which includes a huge overhaul of the codebase. Big thanks to Jordan for that!

Moved settings.py under the data directory, so users don't have to map the settings.py file individually. Now just the /data mapping is all you need (with your settings.py inside the folder). The app will copy your settings.py to /data for you, and then you can delete the old file and mapping.

Removed Readarr support, as the project is archived and the app no longer returns search results.

Also included an update to the German language file.

dataprolet and others added 23 commits December 7, 2024 23:25
- Created ApiClient base class to eliminate code duplication across service clients (Sonarr, Radarr, Readarr)
- Refactored Searcharr class to use modular initialization with better error handling and service discovery
- Modernized codebase to use python-telegram-bot v20+ with async/await pattern
- Improved configuration management with dynamic settings validation and defaults
- Reduced code duplication by ~40% while enhancing maintainability

These architectural improvements establish a more resilient foundation for future enhancements and make the codebase significantly easier to extend.
…arity

This major refactoring transforms the monolithic structure into a structured modular architecture:

- Split the large Searcharr class into specialized modules
- Create dedicated command handlers for each command type
- Implement separate callback handlers for different operations
- Extract utilities for database, conversation, authentication, formatting, and logging
- Add service-specific configuration modules for Sonarr, Radarr, and Readarr
- Improve settings validation and error handling
- Establish proper Python package structure

This change makes the codebase significantly more maintainable, testable, and easier to extend with new features.
- Implement modular callback system with service-specific handlers
- Create separate base utilities for common functionality
- Organize base utilities in dedicated folder structure
- Simplify main callback router with cleaner responsibility delegation
- Update docker-compose.yml to point to the new settings.py path
- Revert main.py to searcharr.py to maintain compatibility with the Docker image
- Bump version from 3.3.0 to 3.4.0
- Updated version from 3.3.0 to 3.4.0
…ted-telegram-bot-library

Complete Refactoring: Modular Architecture, Async Support, and Code Organization
…e-and-updated-telegram-bot-library

Revert "Complete Refactoring: Modular Architecture, Async Support, and Code Organization"
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: jordanella <45442073+jordanella@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add settings auto-migration: settings.py moves to data/ (leveraging
  existing Docker volume mapping), with auto-copy from root on first run
  and warnings when root and data/ settings diverge
- Fix database path resolution (4→3 dirname calls) and restore original
  filename (searcharr.db), with migration from "db" for anyone who ran
  the reverted PR briefly
- Fix log path resolution (4→3 dirname calls)
- Add global configure_logging() so --verbose and --console-logging flags
  propagate to all sub-module loggers instead of being hard-coded off
- Fix api_client.py import (from log → from bot.utils.log)
- Pin python-telegram-bot>=21.0,<23.0 for async API stability
- Remove root __init__.py (project root shouldn't be a package)
- Remove dead root log.py
- Move settings-sample.py back to project root as reference template
- Update docker-compose.yml to remove settings file mapping

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
APScheduler 3.6.3 only supports pytz timezones, but tzlocal 5.x returns
zoneinfo.ZoneInfo objects, causing a TypeError on startup. Pin apscheduler
>=3.10.1 (which added zoneinfo support) and disable the unused job queue
in ApplicationBuilder to avoid eager scheduler initialization.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Child loggers (searcharr.radarr, sonarr, readarr) were propagating records
up to the parent searcharr logger, causing each entry to be handled twice.
Set propagate=False on all loggers since each has its own file handler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Readarr has been retired and was no longer returning search results.
Deleted api/readarr.py, bot/services/readarr_service.py,
bot/callbacks/readarr_callbacks.py, bot/commands/book.py, and
tests/test_readarr.py. Removed all readarr_* settings, language keys,
callback routing, command registration, and formatting code from the
remaining files.

Also updated README.md to reflect that settings now live in data/settings.py
(not the root), consolidate the Docker volume mapping docs to match the
existing docker-compose.yml, and add an upgrade note about auto-migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All flag-carrying callback buttons used ^^ as the separator between
the operation and flags (e.g. add^^p=1), but the callback handler
splits on ^^^ and only reads flags from data[3]. This caused op to
be parsed as "add^^p=1", which matched no handler and silently called
query.answer() instead.

Fixed by aligning the callback_data format in formatting.py to use
^^^ consistently, matching the parser's expectations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After a tag was clicked, the message was re-rendered with the full tag
list (including the just-selected tag), producing an identical markup
and triggering a Telegram BadRequest "Message is not modified" error.

Now already-selected tag IDs are excluded from the re-rendered list.
If all available tags have been selected, fall through to the next
step instead of attempting a no-op message edit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kept our removal of Readarr/book keys (book, readarr_disabled,
include_book_title_in_cmd, no_matching_books, help_readarr,
no_metadata_profiles, add_metadata_button) over beta's additions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- conversation.py generate_cid(): close DB connection before returning
  None on exception (was leaking the connection on every DB error)

- movie.py / series.py: check results before calling generate_cid() and
  create_conversation() — no-results searches were writing orphaned rows
  to the DB and returning without cleaning them up; also guard against
  generate_cid() returning None

- api_client.py _api_get() / _api_post(): remove unreachable `return None`
  after raise_for_status() and correct the docstring to match actual
  behaviour (raises HTTPError on non-2xx, does not return None)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Modular async architecture, Readarr retirement, and bug fixes
@toddrob99 toddrob99 merged commit f1aee09 into main Apr 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants