mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-07-09 12:41:05 +02:00
c8fb72ae9ec23f4d50d7473956c50584e12732e1
995 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c8fb72ae9e |
refactor: split command orchestration handlers (#1155)
## ℹ️ Description - Link to the related issue(s): Issue # - Refactors the CLI command orchestration boundary so command dispatch remains visible while command execution lives in focused handlers. ## 📋 Changes Summary - Split command execution paths in `KleinanzeigenBot.run()` into named handlers for configuration, verification, update checks, content hashing, and ad workflows. - Preserved literal command dispatch cases and command-specific behavior for update checks, download validation, browser login, and cleanup. - Moved German translation keys to the new handler caller names for existing runtime messages. - Added focused tests for update-check behavior, download validation ordering, workspace state usage, and translation key placement. - Lowered the configured branch and cyclomatic complexity limits now that the command orchestration boundary is simpler. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Strengthened code quality standards by implementing stricter complexity thresholds in the development configuration. * **Refactor** * Reorganized command handler architecture to improve internal code structure and maintainability. * **Tests** * Significantly expanded test coverage to validate command execution, argument handling, and translation data integrity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
75f34775e2 |
refactor: reduce return-count complexity (#1154)
## ℹ️ Description - Link to the related issue(s): Issue # - Reduces return-count complexity in the update checker while preserving existing update-check behavior. ## 📋 Changes Summary - Extracted GitHub release selection and commit-ish validation from `check_for_updates` into a private helper. - Moved German translation keys for logger calls that now originate from the helper. - Ratcheted Ruff/Pylint `max-returns` from 10 to 8. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * The update checker now correctly handles the latest update channel by excluding pre-release versions and recommending only stable releases. * **Chores** * Code quality configuration settings were adjusted. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
66cab91898 |
refactor: reduce return-count complexity (#1153)
## ℹ️ Description This refactor reduces return-count complexity for the next PLR0911 ratchet while preserving existing behavior. No related issue. ## 📋 Changes Summary - Extract German and English pluralization helpers while keeping translation and prefix handling in `pluralize()`. - Remove one early return from `check_for_updates()` by sharing the existing final state update/save path. - Ratchet Ruff `PLR0911` `max-returns` from 12 to 10. - Document the one-lower discovery result: `check_for_updates()` is the next limiter at 10 returns for `max-returns = 9`. - No dependencies, configuration requirements, documentation updates, or generated artifacts are introduced. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. No documentation changes were needed. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reorganized pluralization logic and simplified update-checking control flow for improved code maintainability. * **Tests** * Expanded test coverage for pluralization with additional German and English language variations. * **Chores** * Updated code quality configuration standards. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8b0e4f468d |
chore: Update Python dependencies (#1151)
✔ Update pytest 9.1.0 -> 9.1.1 successful ✔ Update msgpack 1.2.0 -> 1.2.1 successful ✔ Update ruff 0.15.17 -> 0.15.18 successful Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
e8752ce10e |
refactor: reduce price reduction complexity (#1152)
## ℹ️ Description - Link to the related issue(s): Issue # - Extracts the first complexity hotspot in the ratcheting sequence by separating the final auto price-reduction application flow from `apply_auto_price_reduction`. - This keeps behavior unchanged while allowing the Ruff `max-returns` transitional limit to move from 13 to 12. ## 📋 Changes Summary - Extracted `_apply_price_reduction_decision` for the final price-reduction mutation/logging phase. - Moved German translations for the relocated `LOG.info` calls to the new helper function key. - Lowered `tool.ruff.lint.pylint.max-returns` from 13 to 12. - No dependency or runtime configuration changes introduced. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) Refactor-only change; none of the listed user-facing change types apply. ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated linting configuration thresholds for code quality standards. * **Refactor** * Improved internal code organization for better maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
801ed0e223 |
refactor: remove KleinanzeigenBot re-export from package root (#1150)
## ℹ️ Description - Link to the related issue(s): N/A - Removes the unsupported package-root `KleinanzeigenBot` re-export after tests were moved to their owning modules. - Updates remaining tests and `conftest.py` to import `KleinanzeigenBot` from `kleinanzeigen_bot.app` directly. - Re-enables Ruff's mccabe complexity checks and tightens high Pylint complexity thresholds left over from the old package-root monolith. ## 📋 Changes Summary - Removed `KleinanzeigenBot` from `src/kleinanzeigen_bot/__init__.py`. - Updated all remaining test imports to use `from kleinanzeigen_bot.app import KleinanzeigenBot`. - Enabled `C90`/mccabe complexity linting with an explicit `max-complexity`. - Lowered the broad Pylint limits for branches, locals, returns, statements, and public methods. - Kept the generated/static pydantic error-code mapping explicitly exempted from complexity checks. - No runtime behavior, CLI, config, translations, or ad YAML changes. - No new dependencies. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [x] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reorganized internal module import structure for consistency across the codebase. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3c17f3c8dd |
refactor: move cross-drive fallback test (#1149)
## ℹ️ Description - Link to the related issue(s): Issue # - Move the Windows cross-drive fallback coverage from the package-init test module into the publishing workflow test suite. - This is a behavior-neutral test organization cleanup. ## 📋 Changes Summary - Moved the cross-drive auto-price-reduction path fallback test into `TestAutoPriceReductionDispatch`. - Deleted the now-empty `tests/unit/test_init.py` and its unused local helpers. - No runtime code, CLI behavior, config, translations, or ad YAML changed. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Reorganized test structure for Windows cross-drive path handling validation to improve maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
48e88fccd3 |
refactor: create app test file and move shell tests (#1148)
## ℹ️ Description - Link to the related issue(s): Issue # - Move app-shell unit tests into a dedicated test module matching `src/kleinanzeigen_bot/app.py`. ## 📋 Changes Summary - Added `tests/unit/test_app.py` for the app-shell test classes and shared fixture. - Kept the cross-drive path fallback coverage in `tests/unit/test_init.py`. - Updated the moved test module to import `KleinanzeigenBot` from `kleinanzeigen_bot.app`. - No runtime, CLI, config, translation, or ad YAML changes. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) - Test organization refactor only. ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added comprehensive unit tests covering command-line subcommands (including defaulting/fallback behavior for ad selector options) and unknown-command handling. * Added assertions for expected initialization behavior and invalid selector validation (including SystemExit code 2). * Refined the unit test modules to simplify imports and improve maintainability, while retaining key cross-drive publish fallback verification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d0d8e5461b |
refactor: move shipping form tests (#1147)
## ℹ️ Description - Link to the related issue(s): Issue # - Move the shipping option mapping test to the publishing form test module, where the browser-level shipping form behavior is owned. ## 📋 Changes Summary - Moved `test_shipping_options_mapping` from `tests/unit/test_init.py` to `tests/unit/test_publishing_form.py`. - Kept the existing assertions and patch targets intact. - Renamed the remaining `test_init.py` class to describe its cross-drive path fallback coverage. - No runtime behavior, CLI, config, translation, or ad YAML changes. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Reorganized test coverage for publishing and shipping functionality * Added tests for Windows cross-drive path fallback behavior * Added tests for shipping options mapping verification <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
824ff70e43 |
refactor: move publishing result tests (#1146)
## ℹ️ Description - Link to the related issue(s): N/A - Moves a focused set of publish-ad orchestration/result tests out of the package initialization test module and into the publishing workflow test module. ## 📋 Changes Summary - Move pre-submit timeout retry coverage into `tests/unit/test_publishing_workflow.py`. - Move WANTED shipping delegation coverage into the publishing workflow tests. - Move auto price reduction dispatch coverage into the publishing workflow tests. - Remove now-unused local fixture/imports from `tests/unit/test_init.py`. - No runtime, CLI, config, translation, or ad YAML changes. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) - [x] Refactor / test organization only ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Adjusted test coverage for internal functionality validation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
01e764a477 |
refactor: move publish uncertainty tests (#1145)
## ℹ️ Description - Link to the related issue(s): Issue # - Moves publish-ad post-submit uncertainty tests into the publishing workflow test module so `test_init.py` keeps shrinking toward initializer-focused coverage. ## 📋 Changes Summary - Moved the post-submit uncertainty `publish_ad()` test slice into `tests/unit/test_publishing_workflow.py`. - Kept the pre-submit retryability test and unrelated initializer/CLI/login/shipping/ad-management tests in `tests/unit/test_init.py`. - Adjusted test imports only; no runtime behavior, configuration, translation, or YAML changes. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Reorganized test coverage for publishing workflows, expanding validation of post-submit error handling and confirmation fallback mechanisms to ensure robust publication behavior under various scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f54521b8e6 |
refactor: move publishing diagnostics tests (#1144)
## ℹ️ Description - Link to the related issue(s): N/A - Move the publish failure diagnostics tests out of the initializer-focused unit test module and into the publishing workflow unit test module. - This is a behavior-neutral test organization change. ## 📋 Changes Summary - Moved `TestKleinanzeigenBotDiagnostics` from `tests/unit/test_init.py` to `tests/unit/test_publishing_workflow.py`. - Kept existing assertions and publishing workflow patch targets unchanged. - Removed stale imports from `tests/unit/test_init.py`. - No runtime, CLI, config, translation, or ad YAML changes. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Enhanced test coverage for diagnostics capture during publishing failures, including verification of log file handling and behavior when diagnostics are disabled. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2332682d07 |
refactor: move publishing orchestration tests (#1143)
## ℹ️ Description - Link to the related issue(s): Issue #977 - Move another focused set of publishing/update orchestration tests out of `tests/unit/test_init.py` and into `tests/unit/test_publishing_workflow.py`. - This is a behavior-neutral test organization change; no runtime, CLI, config, translation, or ad YAML behavior changes are intended. ## 📋 Changes Summary - Moved display counter progression coverage into the publishing workflow test module. - Moved publish-ads orchestration coverage into a dedicated publishing workflow test class. - Cleaned up imports left behind in `tests/unit/test_init.py`. - Dependencies/configuration/additional requirements: none. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) Test-only refactor; none of the listed runtime change categories apply. ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. Not applicable; test-only relocation. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Improved the ad publishing workflow test coverage by reorganizing publish/cleanup, retry behavior, and “no-retry” scenarios. * Added new async testing utilities (including a reusable mocked page) to better simulate browser interactions. * Expanded regression coverage for processing/counter progression across publishing and updating, including paused ads and “not found” cases. * Removed several redundant or replaced counter/retry/skip tests from the prior initialization test module. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
29aed68706 |
refactor: move publishing workflow tests (#1142)
## ℹ️ Description - Link to the related issue(s): Follow-up to #1141 - Move a publishing/update orchestration test slice into the publishing workflow test module. - Share duplicated test fixtures/helpers that are now used by the relocated publishing workflow tests and existing related tests. - This remains behavior-neutral test organization only. ## 📋 Changes Summary - Added `tests/unit/test_publishing_workflow.py` for publishing workflow orchestration tests. - Moved `TestKleinanzeigenBotUpdateAdsResilience` out of `tests/unit/test_init.py`. - Updated the relocated tests to import `KleinanzeigenBot` directly from `kleinanzeigen_bot.app`. - Moved the duplicated `base_ad_config` fixture into `tests/conftest.py`. - Extracted shared `build_update_ad` and `build_published_ads` test helpers into `tests/conftest.py`. - Removed duplicate fixture/helper definitions from affected unit test files. - No runtime behavior, CLI output, config parsing, translations, or ad YAML handling changes. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) - [x] Maintenance/refactor (tests only, no runtime behavior change) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added comprehensive tests for ad publishing resilience and orchestration, covering retry mechanisms, error handling, timeout scenarios, and failure propagation across different ad states * Reorganized and consolidated test utilities, shared fixtures, and builder helpers across test modules <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ee581e383f |
refactor: clean up source hygiene (#1141)
## ℹ️ Description - Link to the related issue(s): Issue # - Clean up minor post-extraction source hygiene without changing runtime behavior. ## 📋 Changes Summary - Import `KleinanzeigenBot` from its concrete `app` module in the CLI. - Update stale source comments/docstrings that referenced the previous package structure. - No dependencies, configuration changes, CLI output changes, translation changes, or ad YAML handling changes. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Refactored internal code organization by adjusting module imports and updating code documentation references to enhance maintainability and clarity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f5f3399a66 |
refactor: move app shell out of package init (#1140)
## ℹ️ Description Move the `KleinanzeigenBot` application class out of `__init__.py` into a dedicated `app.py` module. This continues the maintainability-focused refactoring of the package initializer that was started in prior PRs (login flow extraction, publishing workflow extraction, etc.). - Link to the related issue(s): N/A ## 📋 Changes Summary - **New `src/kleinanzeigen_bot/app.py`** (525 lines): contains the full `KleinanzeigenBot` class with all imports, constructor, `run()` command dispatch, `load_ads()`, and delegator methods - **`src/kleinanzeigen_bot/__init__.py`**: reduced from 545 lines to 27 lines — thin package initializer with `colorama` init, `LOG` setup, `KleinanzeigenBot` re-export from `app.py`, `main()` delegator, and `__name__` guard - **Translations**: split `__init__.py` section header in `translations.de.yaml`; class-owned translations moved to new `kleinanzeigen_bot/app.py:` section - **Tests**: updated patch targets from package-root paths to concrete module paths (`kleinanzeigen_bot.UpdateChecker` → `kleinanzeigen_bot.update_checker.UpdateChecker`) ### ⚙️ Type of Change - [ ] 🐞 Bug fix - [ ] ✨ New feature - [ ] 💥 Breaking change - [x] 🔧 Refactoring (no user-facing behavior changes) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Centralized runtime command handling in a new application entrypoint class while keeping the same CLI-style command set. * Slimmed the package initializer to re-export the main bot class and delegate CLI execution through `main(args)`. * **Bug Fixes** * Improved Windows console compatibility during startup. * **Tests** * Updated unit tests and mocks to reflect the new location of command-handling logic and related wiring. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d3507c0ff5 |
chore: Update Python dependencies (#1138)
✔ Update certifi 2026.5.20 -> 2026.6.17 successful ✔ Update cyclonedx-python-lib 11.10.0 -> 11.11.0 successful Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
35bd393dc4 |
refactor: extract login/auth flow into login_flow.py (#1139)
## ℹ️ Description Extract all login, Auth0 form-fill, captcha, SMS/email verification, GDPR, login-state detection, and diagnostics-capture logic from `__init__.py` into a new `login_flow.py` module. ## 📋 Changes Summary - Create `login_flow.py` (~634 lines) with module-level async functions accepting explicit `web: WebScrapingMixin` + keyword arguments - Thin delegators in `__init__.py` bind `KleinanzeigenBot` instance attributes to module calls - Remove 12 dead delegator methods; tests call module functions directly - Move `LoginDetectionResult`/`LoginDetectionReason` types to `login_flow` - Move `TestKleinanzeigenBotAuthentication` to `tests/unit/test_login_flow.py`, update patch targets - Move login translations to `login_flow.py` section in `translations.de.yaml` - Fix diagnostics guard reset per login attempt - Remove `is_logged_in_web()`; pass username explicitly - Make cross-module functions public: `login_flow` internal helpers and `WebScrapingMixin` helpers (`dismiss_consent_banner`, `effective_timeout`, `extract_visible_text`) ### ⚙️ Type of Change - [x] ✨ New feature (adds new functionality without breaking existing usage) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Reworked the authentication/login process to use a dedicated login flow, improving handling of multi-step sign-in and related verification prompts. * Standardized login-status detection and diagnostics behavior when login state can’t be determined. * Updated text-extraction and timeout behavior for DOM-based fallbacks, and aligned consent-banner dismissal to the public API. * **Tests** * Added extensive unit tests for the login flow and login-state detection. * Updated existing tests to reflect the refactored helpers and consent-banner method naming. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ecd3ea35cf |
refactor: extract publishing workflow (#1137)
## ℹ️ Description - Link to the related issue(s): N/A - Extracts publish/update orchestration from the monolithic bot class into `publishing_workflow.py` as Step 21 of the monolith breakdown. ## 📋 Changes Summary - Added `src/kleinanzeigen_bot/publishing_workflow.py` for publish/update orchestration, retry/uncertainty handling, result checks, and delete-before/after-publish wiring. - Kept `KleinanzeigenBot` publish/update methods as narrow delegation seams with explicit dependencies. - Moved WANTED ad type selection into `publishing_form.fill_ad_form()` so form details stay in the form module. - Updated German translations and unit tests to patch concrete workflow module paths. - No dependency or configuration changes. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) - [x] Refactor (no user-facing behavior change) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved form rendering for WANTED ad type by ensuring the ad type is pre-selected before populating other form fields. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
eae9dc9fc1 |
refactor: extract publishing form orchestrator (#1136)
## ℹ️ Description Move the last form-filling remnant out of `__init__.py` into `publishing_form.py`, where all individual form section functions already live. - `_fill_ad_form()` only delegated to the already-extracted section functions (`set_category`, `set_special_attributes`, `set_shipping_form`, `set_pricing_fields`, `set_contact_fields`, `fill_image_section`). - Replaced with a public module-level `publishing_form.fill_ad_form()` that accepts explicit `web`, `root_url`, `ad_defaults`, `ad_file`, `ad_cfg`, and `mode` parameters. - `publish_ad()` now calls `_publishing_form.fill_ad_form(self, ...)` instead of `self._fill_ad_form(...)`. ## 📋 Changes Summary - Extracted `fill_ad_form()` into `publishing_form.py` as a public module-level async function - Removed `_fill_ad_form()` method from `KleinanzeigenBot` class - Updated call site in `publish_ad()` to pass explicit parameters - Updated test patch target in `test_publishing_persistence.py` and docstring in `test_init.py` ### ⚙️ Type of Change - [ ] 🐞 Bug fix - [ ] ✨ New feature - [ ] 💥 Breaking change ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reorganized ad form-filling logic for improved maintainability and code structure. * **Tests** * Updated unit tests to reflect internal code reorganization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
154c37b26e |
refactor: extract special-attributes/condition form section (#1135)
## ℹ️ Description Extracts special-attribute and condition form logic from `__init__.py` into `publishing_form.py` to continue module decomposition. ## 📋 Changes Summary - **`publishing_form.py`**: Added `set_special_attributes`, `_set_condition`, and helpers (`_pick_special_attribute_candidate`, `_special_attribute_candidate_priority`, `_describe_special_attribute_candidate`) adapted as module-level functions taking `web: WebScrapingMixin` - **`__init__.py`**: Removed the moved functions, cleaned up stale imports (`re`, `_ad_form_helpers`, `_select_button_combobox`, `ensure`, `Element`), updated `_fill_ad_form` to delegate via `_publishing_form.set_special_attributes()` - **`translations.de.yaml`**: Moved `_set_condition` and `set_special_attributes` sections from `__init__.py:` → `publishing_form.py:` block - **`test_init.py`**: Moved special-attribute and condition tests to `test_publishing_form.py`, updated orchestration patch targets - **`test_publishing_form.py`**: Added `TestSpecialAttributes`, `TestConditionSelector`, and `TestConditionFallbackToGenericHandler` classes with adapted imports and patches ### ⚙️ Type of Change - [x] Refactor — no behavior changes, internal module reorganization only ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. |
||
|
|
875b8b063a |
refactor: extract publishing shipping form section (#1134)
## ℹ️ Description - Extracts the publishing shipping form workflow from `KleinanzeigenBot` into `publishing_form.py`. - Keeps runtime behavior, selectors, waits, messages, and browser interactions unchanged while moving translation ownership. ## 📋 Changes Summary - Move WANTED shipping handling, shipping radio/dialog handling, shipping option toggling, and the private React-fiber button-combobox helper into `publishing_form.py`. - Update `__init__.py` to delegate shipping form work and keep only orchestration/seam responsibilities. - Move direct shipping behavior tests to `tests/unit/test_publishing_form.py`; keep a shipping orchestration seam test in `tests/unit/test_init.py`. - Move German translation entries for shipping messages to the `publishing_form.py` translation section. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary of changes * **Refactor** * Improved publishing ad shipping form handling by routing wanted vs non-wanted ads to the correct UI flow. * Enhanced Versand (shipping) combobox selection for wanted ads to ensure the right option is chosen. * Strengthened the shipping dialog flow for pickup vs shipping-with-options, including more reliable shipping price confirmation and retry behavior. * **Tests** * Expanded unit tests covering shipping dialog interactions, carrier/option selection, wanted-shipping combobox behavior, and timeout/error scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e9ed698dce |
refactor: extract publishing pricing form section (#1133)
## ℹ️ Description - Link to the related issue(s): Issue # - Extracts the publishing pricing/direct-buy/description form section from the main bot class as the next monolith-breakdown step. ## 📋 Changes Summary - Added publishing_form.set_pricing_fields() for price type/amount, sell-directly/direct-buy radios, and description filling. - Replaced the inline _fill_ad_form() pricing block with the new publishing form section call. - Moved direct unit coverage for pricing/direct-buy/description behavior into test_publishing_form.py and kept orchestration seam tests in test_init.py. - Moved existing German translation ownership entries to the new function path without wording changes. - No dependencies, configuration changes, CLI changes, schema changes, or generated artifacts. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (pdm run test). - [x] I have formatted the code (pdm run format). - [x] I have verified that linting passes (pdm run lint). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Centralized pricing-related ad form filling (price type, price amount, ad description with affixes, and direct-buy/buy-now controls) into a shared publishing helper for more consistent behavior. * **Bug Fixes** * Improved handling of pricing/buy-now selection failures by surfacing clearer, localized timeout errors. * **Tests** * Added dedicated coverage for pricing field interactions, including dropdown skipping when not applicable, correct amount input behavior, and description generation usage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
137a7691a7 |
refactor: extract publishing image form section (#1132)
## ℹ️ Description - Link to the related issue(s): N/A - Extracts the publishing image cleanup and upload section from the bot monolith into `publishing_form.py` as Step 16 of the monolith breakdown plan. ## 📋 Changes Summary - Move image cleanup/upload behavior into `fill_image_section()` and `upload_images()`. - Replace the monolith image block with a publishing form seam call. - Move direct image behavior tests from `test_init.py` to `test_publishing_form.py`. - Update German translation ownership paths without changing translated text. - No dependency, configuration, CLI, schema, or generated artifact changes. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) - [x] ♻️ Refactor (no intended behavior change) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Image upload handling has been reorganized and consolidated in the publishing module for improved code organization. The image processing workflow now includes enhanced timeout management and marker-based completion detection to ensure all images are reliably processed during ad publication. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9d146c2b96 |
refactor: extract publishing contact form section (#1131)
## ℹ️ Description - Link to the related issue(s): Issue # - Refactors the publishing form code by moving the contact/location form section out of the package initializer into the publishing form module. ## 📋 Changes Summary - Move contact field handling, contact location handling, and city combobox helpers into publishing_form.py. - Keep the publishing form orchestration delegating through an explicit web/contact boundary. - Update unit tests to patch and call the new publishing form functions. - Move German translation ownership paths for the relocated messages without changing translated text. - No dependencies, configuration changes, or additional requirements introduced. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (pdm run test). - [x] I have formatted the code (pdm run format). - [x] I have verified that linting passes (pdm run lint). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Updated ad publishing to populate contact and location fields via dedicated public publishing-form helpers, with revised import wiring for ad model types. * Removed older internal city/contact handling logic and replaced it with clearer helper-driven flow. * **Bug Fixes** * Improved city/location hardening: safer city extraction, combobox-style selection with ambiguity checks, timeout-based fallbacks, and correct handling for read-only city inputs. * More resilient contact field population (zipcode/location, street, name, phone), with graceful handling when optional elements are missing. * **Tests** * Added/updated unit tests to cover city/contact hardening and category probe/picker selection behaviors, asserting helper calls rather than private methods. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f02816cb06 |
refactor: extract publishing category form section (#1130)
## ℹ️ Description - Link to the related issue(s): N/A - Extracts the publishing category form section from the monolithic bot class into a focused publishing form module while preserving category selection and suggestion fallback behavior. ## 📋 Changes Summary - Move category selection and category suggestion fallback into `src/kleinanzeigen_bot/publishing_form.py`. - Update publish form orchestration to call the extracted category function through a narrow web/root_url boundary. - Update unit tests and German translation ownership for the new module path. - No dependencies, configuration changes, or additional requirements introduced. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Restructured category selection logic for improved maintainability and code organization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dd6a1955ef |
refactor: extract publishing form helpers (#1129)
## ℹ️ Description - Extract browser-independent publishing form helpers from the monolith into `ad_form_helpers.py`. - Prepares later publishing form extraction without changing browser behavior. ## 📋 Changes Summary - Move the Versand combobox selector constant to `ad_form_helpers.py`. - Move location matching logic to `ad_form_helpers.py`. - Update production call sites and helper ownership tests. - Keep form sections and browser-dependent logic in `__init__.py`. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved internal code organization by consolidating shared helpers for form-related utilities and location matching logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
fda56b109c |
refactor: prepare web helpers for publishing form extraction (#1128)
## ℹ️ Description - Link to the related issue(s): Issue #930 - Moves a shared consent-banner browser helper onto the generic web scraping mixin so later publishing form refactors can use it without depending on the main bot class. ## 📋 Changes Summary - Move `_dismiss_consent_banner()` from `KleinanzeigenBot` to `WebScrapingMixin` without changing selector, timeout, click, or sleep behavior. - Move the helper's focused unit tests from `test_init.py` to `test_web_scraping_mixin.py`. - No dependencies, configuration changes, or additional requirements introduced. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) None of the listed categories apply; this is an internal behavior-equivalent refactor. ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Moved consent-banner dismissal logic into a shared web-scraping helper, and updated the bot flow to proceed directly after SMS verification. * **Tests** * Removed unit tests that covered the old bot-level consent-banner handling. * Added new async unit tests to verify the shared helper clicks the consent accept button when present and does nothing when absent. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
816cf3ed9e |
refactor: rename publishing persistence module (#1127)
## ℹ️ Description - Link to the related issue(s): Issue # - Rename the persistence-only publishing module so the module name matches its current responsibility. ## 📋 Changes Summary - Rename `publishing_flow.py` to `publishing_persistence.py`. - Update production imports/calls and test patch paths. - Move persistence tests to `test_publishing_persistence.py` and keep submission tests under `test_publishing_submission.py`. - Update the German translation section header for the renamed module. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved the way published ad changes are saved after submitting or updating, ensuring related fields (such as image updates and pricing adjustments) are correctly retained. * **Bug Fixes** * Publishing now continues even if the follow-up save step fails, preventing unnecessary interruptions. * **Tests** * Updated existing tests to match the revised persistence behavior. * Added new unit tests covering persistence outcomes, logging, rollback behavior, and image/price update handling. * Simplified the publishing submission test suite setup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5c22795728 |
fix: handle shipping select for pro accounts (#1126)
## ℹ️ Description - Link to the related issue(s): Issue #1125 - Fixes PRO/commercial account publishing where the Versand field is rendered as a custom `button[role="combobox"]` dropdown by the PostListingForm Astro island, not as a native `versand_s` `<select>` and not as the private-account radio-button UI. - Uses the confirmed PRO DOM model from the issue comments/screenshots: category-prefixed IDs such as `kunst.versand` / `uhren.versand`, placeholder `Bitte wählen`, and options `Versand möglich` (`ja`) / `Nur Abholung` (`nein`). ## 📋 Changes Summary - Detect the custom Versand combobox before falling back to the private radio/dialog shipping flow. - Locate the combobox by the confirmed category-prefixed id shape and by the selected-option label relationship (`aria-labelledby$="versand-selected-option"`) so the lookup is not tied to one category prefix. - Select `Versand möglich` for `shipping_type: SHIPPING` and `Nur Abholung` for `shipping_type: PICKUP` by visible option text via `web_select_button_combobox()`. - Apply the same safer Versand combobox selector to the existing WANTED-ad shipping combobox path. - Keep the private/non-commercial radio-button and shipping-options-dialog path as the fallback when the custom combobox is absent. - Add regression coverage for the PRO combobox path and relax existing shipping-flow assertions so they check behavior instead of exact probe ordering/timeout plumbing. - Add the German translation for the combobox error message. ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved the WANTED shipping flow to detect and use native “Versand” dropdown controls when available, selecting the correct shipping option directly. * **Bug Fixes** * Added clearer errors for unsupported shipping types and standardized timeout behavior when native selection fails; continues to fall back to the existing radio/dialog approach when the control is missing. * **Tests** * Expanded unit tests to cover the native Versand combobox route, including selector coverage and updated probe/call-order expectations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
021b887d08 |
chore: Update Python dependencies (#1124)
✔ Update filelock 3.29.3 -> 3.29.4 successful ✔ Update pytest 9.0.3 -> 9.1.0 successful ✔ Update pyinstaller 6.20.0 -> 6.21.0 successful ✔ Update basedpyright 1.39.7 -> 1.39.8 successful Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
f94567a983 |
fix: use canonical title for owned ad downloads (#1123)
## ℹ️ Description - Link to the related issue(s): Issue #1119 - Fixes owned-ad downloads where the public/detail page title may include UI status decoration that makes the title exceed the semantic 65-character title limit. ## 📋 Changes Summary - Resolve download titles once via manage-ads metadata when available. - Reuse the resolved title for folder naming, file stems, and persisted ad config data. - Keep manual page title extraction as the fallback without stripping or truncation. - Add regression coverage for canonical metadata titles and fallback extraction. ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (pdm run test). - [x] I have formatted the code (pdm run format). - [x] I have verified that linting passes (pdm run lint). - [x] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Enhanced ad title resolution to prioritize cached published metadata when available, with fallback to page extraction for improved reliability. * Improved directory handling to consistently use the resolved ad title for naming and saved info templates. * **Bug Fixes** * Corrected title/metadata extraction flow to avoid redundant title reads and ensure creation dates are reliably sourced from the expected page elements. * **Tests** * Updated and added unit test coverage for title resolution, directory behaviors, and extraction call ordering. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
439c36e851 |
fix: click Auth0 Weiter after captcha (#1120) (#1122)
## ℹ️ Description Fixes issue #1120 by handling the Auth0 captcha branch after email submit. When captcha appears, the bot now probes for a visible/clickable "Weiter" button and clicks it before waiting for the password page. The normal no-captcha login flow remains unchanged. - Link to the related issue(s): Issue #1120 - Describe the motivation and context for this change. ## 📋 Changes Summary - Added a captcha-only Auth0 identifier handler that waits for captcha completion, probes for "Weiter" with `web_probe`, and clicks it if present. - Kept the existing no-captcha login path unchanged. - Updated German translations for the new log messages. - Adjusted unit tests for the new login helper. ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. No additional docs changes were needed beyond translations. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved login robustness to detect optional reCAPTCHA on the email/identifier step; users are notified when a captcha appears, can provide input, and the login resumes once advanced. * **Tests** * Updated unit tests to cover and control the captcha-handling behavior during the login flow, including the missing-password-step scenario. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5d5c25d753 |
refactor: extract publishing submission flow (#1121)
## ℹ️ Description *Refactor the publishing submission/confirmation flow into a dedicated module while keeping behavior identical.* - Link to the related issue(s): N/A - Describe the motivation and context for this change: Reduce coupling in the publishing workflow and keep the persistence boundary separate. ## 📋 Changes Summary - Added `src/kleinanzeigen_bot/publishing_submission.py` for captcha, submit, confirmation, and ad-id recovery. - Removed the submission/confirmation helpers from `publishing_flow.py`, leaving persistence helpers there. - Updated the `publish_ad()` call site and tests to use the new concrete module path. - Moved the translated log-message entries for the extracted submission flow. ### ⚙️ Type of Change Select the type(s) of change(s) included in this pull request: - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist Before requesting a review, confirm the following: - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [ ] I have updated documentation where necessary. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Ad submission and confirmation logic moved into a dedicated submission module for clearer separation. * **Bug Fixes** * Improved publish confirmation: better captcha handling, post-submit dialogs (upsell/payment, imprint guidance, “no image”) and avoidance of stale-referrer fallbacks. * Now fails loudly and avoids persisting when ad confirmation is uncertain. * **Tests** * Unit tests updated to target the new submission flow and recovery/persistence behaviors. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9172af0c69 |
enh: skip runtime bootstrap for update-check command (#1117)
## ℹ️ Description The `update-check` command was calling `_bootstrap_runtime()` which triggered config file creation (`create_default_config`), file logging setup, and browser config application. None of these are needed for a read-only GitHub release version check. This PR skips the full bootstrap and instead uses `UpdateChecker` with sensible defaults from `Config()` and a state path resolved from the already-available workspace. Closes #1090. ## 📋 Changes Summary ### 🚀 Enhancement - **`src/kleinanzeigen_bot/__init__.py`** — `update-check` case: removed `_bootstrap_runtime()` call, uses `self.config = Config()` with sensible defaults, state path from already-resolved `self.workspace`. ### ⚙️ Type of Change - [x] 🚀 New feature / Enhancement (non-breaking change which adds functionality) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. |
||
|
|
97256c1d70 |
fix: apply after_delete policy when title-mode delete returns all-404 with id=None (#1116)
## ℹ️ Description When `delete_old_ads_by_title=True` and `ad_cfg.id=None` and all remote DELETE requests return 404, the `after_delete` policy (DISABLE/RESET) was silently skipped because the orchestrator's `id_before`/`id_after` heuristic could not distinguish "not attempted" from "attempted but all 404." This PR replaces the heuristic with an explicit `DeleteResult` NamedTuple returned from `delete_ad()`, communicating whether HTTP DELETE requests were actually sent (`attempted`) separately from whether any returned 200 (`deleted`). Closes #1103. ## 📋 Changes Summary ### 🐞 Bug fix - **`delete_flow.py`** — New `DeleteResult(deleted, attempted)` NamedTuple replaces the `bool` return from `delete_ad()`. The orchestrator now uses `result.attempted` directly to decide whether to apply `after_delete` policy. - Removed the fragile `id_before`/`ad_cfg.id`-based heuristic entirely. ### 🧪 Tests - Updated all 9 existing `delete_ad()` tests for the new tuple return type - Updated 3 orchestrator tests (`delete_ads`) for the new `DeleteResult` API - Added regression test `test_cleanup_on_title_match_all_404_with_id_none` — `ad_cfg.id=None`, title-match, all responses 404, `after_delete=RESET` is applied ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved deletion tracking to distinguish attempted vs successful deletions, ensuring cleanup policies run correctly across edge cases. * **Tests** * Updated unit tests to reflect the new deletion outcomes and added a regression test to verify cleanup behavior when title-mode deletions all fail. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4ec4e802fd |
chore: ✔ Update ruff 0.15.16 -> 0.15.17 (#1108)
✔ Update ruff 0.15.16 -> 0.15.17 successful Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
f1e37c6f58 |
fix: disable diagnostics timing collection by default (#1115)
## ℹ️ Description Change the `diagnostics.timing_collection` default from `true` to `false` so that timeout timing data is only collected when a user explicitly opts in. ## 📋 Changes Summary - `model/config_model.py`: changed `TimingCollectionConfig.timing_collection` default from `True` to `False` - `schemas/config.schema.json`: regenerated with `"default": false` - `docs/config.default.yaml`: regenerated with `timing_collection: false` Existing configs that explicitly set `timing_collection: true` are unaffected. ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [x] 💥 Breaking change (changes default behavior — users who relied on the implicit `true` default must now explicitly enable it) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. |
||
|
|
d2b944568c |
fix: close submit uncertainty gap, surface silent TOCTOU race, and translate remaining TimeoutError messages (#1114)
## ℹ️ Description Three bug fixes affecting browser automation correctness and i18n completeness: - **#1110**: Move upsell dialog dismiss inside the post-submit try/except block so timeouts during upsell interaction are treated as uncertain submission rather than retryable errors, preventing duplicate listings. - **#1112**: Change `web_set_input_value` to detect TOCTOU races (element disappearing between `web_find` and JS execution). The JS now returns `false` on missing element, and the Python side raises `TimeoutError` so callers see a clear failure instead of proceeding with stale field data. **Approach**: sentinel return (not JS throw) because nodriver returns `ExceptionDetails` silently rather than raising Python exceptions. - Translate two remaining untranslated `TimeoutError` messages in `__init__.py:_set_condition` and `web_scraping_mixin.py:_run_with_timeout_retries`. ## 📋 Changes Summary | File | Change | |---|---| | `publishing_flow.py` | Move upsell dismiss inside `try` block (#1110) | | `web_scraping_mixin.py` | Sentinel + `TimeoutError` for TOCTOU race (#1112); translate guard-clause message | | `__init__.py` | Translate `No condition radio matched values` message | | `translations.de.yaml` | Add German translations for all 3 new messages | ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved and localized error messages for timeouts and form interactions. * Better handling of element race conditions to reduce submission failures. * **Refactor** * Reworked ad submission confirmation flow to unify exception handling and make upsell dismissal more robust. * **Tests** * Added tests covering input-setting behavior and TOCTOU race handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ce3c1adf89 |
fix: correct republication timing and content hash computation (#1113)
## ℹ️ Description Two small bug fixes affecting ad lifecycle correctness, both in `ad_loading.py`. - Fix off-by-one republication comparison (#1099): ads are now eligible for republication exactly when their age reaches the configured interval, instead of one day late. - Fix content hash divergence (#1100): `update-content-hash` now computes hashes from the raw ad config (matching `check_ad_changed`), preventing spurious "ad changed" detection on every publish. ## 📋 Changes Summary ### 🐞 Bug fixes 1. **#1099** — `check_ad_republication`: changed `<=` to `<` so ads are due at `ad_age.days == republication_interval` rather than one day later. 2. **#1100** — `update_content_hashes`: switched from `ad_cfg.update_content_hash()` (hydrated Ad model) to `AdPartial.model_validate(ad_cfg_orig).update_content_hash()` (raw config dict), matching `check_ad_changed`. Also uses `.get()` to handle legacy ad files without a `content_hash` key. ### 🧪 Tests Updated `test_counter_progression` to pre-compute hashes using the same `AdPartial` path as production code. ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Adjusted ad republication timing logic—ads at the republication interval boundary are now correctly treated as not yet due for republication. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2971d650c7 |
refactor: extract captcha flow and submit/confirm to dedicated modules (#1111)
## ℹ️ Description Extract captcha detection and ad submit/confirmation logic from `__init__.py` into focused modules. This is part of an ongoing effort to decompose the monolithic `KleinanzeigenBot` class into maintainable, testable module functions with explicit dependencies. - Related to #1110 (pre-existing submit uncertainty boundary gap, tracked separately) ## 📋 Changes Summary - **New module `captcha_flow.py`**: `check_and_wait_for_captcha()` shared by login and publish flows. Captcha auto-restart raises `CaptchaEncountered` on non-login pages. - **`publishing_flow.py` gains `submit_and_confirm_ad()`**: submit click, upsell dismissal, imprint guidance, no-image confirmation, payment form detection, confirmation URL polling with tracking-data fallback, ad ID extraction. Plus private `_try_recover_ad_id_from_redirect()`. - **`web_set_input_value()` promoted to `WebScrapingMixin`**: generic browser primitive for setting DOM values with React-compatible events. Removed from bot class. - **Translations moved** to match new module/key locations. - **Coverage**: `captcha_flow.py` 100%, `publishing_flow.py` 90.78% (up from 83.98%). - **Cleanup**: removals from `__init__.py` (233 lines), stale/low-value tests removed from `test_init.py`. No CLI, config, YAML, or runtime behavior changes. ### ⚙️ Type of Change - [x] ✨ New feature (adds new functionality without breaking existing usage) — technically a refactor; no behavioral changes ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * More reliable ad publishing with a fallback recovery when confirmation fails * Improved shipping-price entry with read-back verification and automatic retries * More consistent form field handling (contact info, price, description) and improved captcha prompting during login * **Refactor** * Internal publishing and captcha flows reorganized for more robust user interactions * **Tests** * Added extensive tests for captcha handling and ad submission/confirmation flows <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a86e9d5d5e |
refactor: extract persist_published_ad() to publishing_flow.py (#1107)
## ℹ️ Description Extract post-publish persistence from `KleinanzeigenBot` into a new `publishing_flow` module, establishing the first publishing-domain extraction following the pattern used for `delete_flow`, `extend_flow`, and `download_flow`. ## 📋 Changes Summary - **New module `publishing_flow.py`** (~140 lines) with two functions: - `persist_published_ad()` — public boundary: YAML field updates, content hash, timestamps, repost/price-reduction counters, save, rollback, and local path renaming - `\_log\_local\_path\_rename\_result()` — module-private logging helper - **`__init__.py`**: added `publishing_flow` import, replaced `await self.\_persist\_published\_ad(...)` with `publishing\_flow.persist\_published\_ad(...)` (sync call, no await), removed both methods (~120 lines) - Cleaned up unused imports in `__init__.py`: `AdPartial`, `replace`, `_local_path_renaming`, `_dicts` - Translation sections moved from `__init__.py` to `publishing_flow.py` in `translations.de.yaml` ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) Internal refactoring only — no user-facing behavior or CLI changes. ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Post-publication persistence moved into a dedicated publishing flow to centralize ad update and rename handling. * **Improvements** * Enhanced logging and handling of local file/folder renames after publication. * Updated persisted ad metadata after publish (IDs, content hashes, timestamps, repost and price-reduction counts). * **Bug Fixes** * Publishing now catches and logs persistence failures instead of letting them propagate. * **Tests** * Added unit tests for rename logging, persistence behavior, rollback on save failure, and resilience to persistence errors. * **Chores** * Updated file copyright headers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
38399f4dfe |
refactor: split publish_ad() into three named private methods (#1106)
## ℹ️ Description Decompose the ~350-line `publish_ad()` monolith into three named private methods on `KleinanzeigenBot`, creating explicit seams before eventual module extraction. ## 📋 Changes Summary - **`_fill_ad_form()`** — form filling: category, special attributes, shipping, price, sell-directly, description, contact, image cleanup, image upload - **`_submit_and_confirm_ad()`** — submission: captcha, title, submit click, upsell dismissal, confirmation URL polling, ad-ID extraction + fallback recovery. Returns ad_id. - **`_persist_published_ad()`** — post-publish persistence: update fields, content_hash, timestamps, repost_count, price_reduction_count; save file; local path renaming; log result - **Prelude** (~33 lines) stays inline: mode-dependent setup, price reduction, page navigation - Dropped stale `noqa` complexity comments on `publish_ad()` (now ~45 lines) - Translation sections split to match new method names ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) Internal refactoring only — no user-facing behavior or CLI changes. ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved ad publishing workflow for more reliable publish/update operations. * Better handling of replace vs modify publishing modes. * Automatic dismissal of consent banner during publishing. * UI switch for WANTED-type ads applied automatically. * More robust recovery and persistence of published ad IDs, image renaming, timestamps and counters to prevent inconsistencies. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9b265c7cdb |
refactor: extract _delete_old_ad_if_needed helper from publish paths (#1105)
## ℹ️ Description Replace two near-duplicate delete-guard blocks in `publish_ads()` (`AFTER_PUBLISH`) and `publish_ad()` (`BEFORE_PUBLISH`) with a single `KleinanzeigenBot._delete_old_ad_if_needed()` private method that centralises `keep_old_ads`, `delete_old_ads` timing, and title-based-deletion logic. ## 📋 Changes Summary - **New helper** `_delete_old_ad_if_needed(ad_cfg, published_ads_list, *, timing)` centralises `keep_old_ads`, `delete_old_ads` timing, and title-based-deletion guards; delegates to `delete_flow.delete_ad()` - **`publish_ads` AFTER_PUBLISH**: 7-line `if success and ... and not keep_old_ads:` + `delete_flow.delete_ad()` → 1-line call inside existing `if success:` block - **`publish_ad` BEFORE_PUBLISH**: Nested 7-line guard + `delete_flow.delete_ad()` → 1-line call under existing `if mode == REPLACE:` - Added `Literal` to typing import ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) Internal refactoring only — no user-facing behavior or CLI changes. ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Consolidated internal logic for ad deletion handling to improve code organization and maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b256232939 |
refactor: rename form methods and remove fetch delegator in preparation for publishing workflow extraction (#1104)
## ℹ️ Description Mechanical prep work for the publishing/update workflow extraction. No behavior changes — purely renaming and cleanup. ## 📋 Changes Summary - Rename 19 double-underscore form methods (`__method` → `_method`) in `__init__.py` - Remove the temporary `_fetch_published_ads()` delegator; `publish_ads()` and `update_ads()` now call `published_ads.fetch_published_ads()` directly - Fix local variable naming in publish/update to use `published_ads_list` to avoid shadowing the `published_ads` module - Update 95 test references from mangled names (`_KleinanzeigenBot__*`) to single-underscore names (`_*`) - Update 8 test patches from `patch.object(test_bot, "_fetch_published_ads", ...)` to `patch("kleinanzeigen_bot.published_ads.fetch_published_ads", ...)` - Update 10 translation section headers in `translations.de.yaml` to match renamed method names - Preserve `@staticmethod` decorators on `_location_matches_target`, `_special_attribute_candidate_priority`, and `_describe_special_attribute_candidate` ### ⚙️ Type of Change - [x] ✨ New feature (adds new functionality without breaking existing usage) → Actually a refactor: no user-facing changes, purely internal restructuring. ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved shipping price persistence with retry logic to ensure values are correctly set and verified. * **Refactor** * Internal code structure improvements for better maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7803872422 |
refactor: extract delete, extend, download workflows and published-ad fetch into focused modules (#1101)
## ℹ️ Description > **Why one PR?** The four extractions are mechanically identical: extract a method body into a module function, replace `self.*` with explicit parameters, update call sites in `run()`. Splitting into 4 sequential PRs would produce repetitive diffs against the same `__init__.py`, compound rebase friction, and add no independent review signal — each PR would be reviewed as "same pattern, different function." Combined, the mechanical nature is visible at a glance and the 17 files are mostly new modules + focused test files. Reduce KleinanzeigenBot.__init__.py from 2865 to 2391 lines by extracting four browser workflow modules with explicit dependencies. ## 📋 Changes Summary - New `published_ads.py` — `fetch_published_ads()` and `PublishedAdsFetchIncompleteError`, shared by all workflows - New `delete_flow.py` — `delete_ads()` orchestrator and `delete_ad()` single-ad deletion - New `extend_flow.py` — `extend_ads()` orchestrator and `_extend_ad()` single-ad extension - New `download_flow.py` — `download_ads()`, `resolve_download_dir()`, and `_download_ad_with_resolved_state()` - Promote `_timeout` and `_navigate_paginated_ad_overview` to public in WebScrapingMixin - Restore `PublishedAdsFetchIncompleteError` base class to KleinanzeigenBotError - New focused test files: `test_published_ads.py` (17), `test_delete_flow.py` (13), `test_extend_flow.py` (17), `test_download_flow.py` (16) - Removed: `test_json_pagination.py`, `test_extend_command.py` - Flow modules receive explicit dependencies (`web`, `root_url`, `config`, `workspace`, `load_ads_func`) — no `do_work(bot)` signatures - Temporary `_fetch_published_ads` delegator kept on bot (still used by publish/update) ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [x] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified timeout configuration guidance and examples (use public timeout API and when to use effective timeout). * **New Features** * Added workflows to delete, download (all/new/IDs) and extend ads; added API-backed published-ads retrieval and safe ID matching. * **Refactor** * Command routing moved to workflow modules; unified timeout and pagination helpers for consistent UI/navigation behavior. * **Tests** * Expanded/updated unit tests covering deletion, download, extension, pagination, timeout and related edge cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
eeafd64280 | chore: Update Python dependencies (#1095) | ||
|
|
20be5e9528 |
refactor: extract ad loading and selector resolution into ad_loading.py (#1098)
## ℹ️ Description Extract browser-free ad discovery, validation, selector filtering, category resolution, content-hash helpers, and image globbing from `__init__.py` into a new `ad_loading.py` module with explicit dependencies. Non-breaking internal refactor — no CLI, config, or user-facing behavior changes. ## 📋 Changes Summary - **New module** `src/kleinanzeigen_bot/ad_loading.py` (373 lines) with 9 public functions - **Removed** `_is_valid_ads_selector`, `__check_ad_republication`, `__check_ad_changed`, `load_ad`, `update_content_hashes` from `KleinanzeigenBot` - `load_ads()` kept as temporary delegator (7+ call sites in `run()` / `download_ads()`) - **37 focused tests** in `tests/unit/test_ad_loading.py` - **Removed** 14 duplicate tests from `tests/unit/test_init.py` - **Translations** moved from `__init__.py` to `ad_loading.py` function names ### ⚙️ Type of Change - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) - [x] ✨ New feature (adds new functionality without breaking existing usage) - [ ] 💥 Breaking change (changes that might break existing user setups, scripts, or configurations) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project's standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Moved ad discovery, validation, filtering, image/category resolution, and content-hash management into a dedicated ad-loading component; CLI selector validation and content-hash updates now use that shared logic. * **Tests** * Added comprehensive unit tests for ad discovery, selector parsing/validation, change detection, republication rules, image/category resolution, and content-hash update behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c7f16e3361 |
fix: add fallback for button-combobox special attributes after site redesign (#1097)
## ℹ️ Description After the Kleinanzeigen.de React redesign, category-specific fields like Größe, Farbe, and Mädchen & Jungen are rendered as `<button role="combobox">` whose IDs may not match the existing XPath patterns used by `__set_special_attributes`. When the XPath only matches the backing hidden `<input type="hidden" name="attributeMap[...]">`, the handler falls through to the text-input branch and fails. - Fixes: #1096 ## 📋 Changes Summary - Added `_find_associated_button_combobox()` to `web_scraping_mixin.py` — a JS-based fallback that locates the associated `<button role="combobox">` by searching for the backing hidden input and walking up the DOM tree - Integrated the fallback into `__set_special_attributes`: when the matched element is `type="hidden"`, searches for an associated button and routes to `__select_button_combobox` - Added 3 unit tests covering: fallback finds button, no button found falls through, fallback not triggered when button directly matched ### ⚙️ Type of Change - [x] 🐞 Bug fix (non-breaking change which fixes an issue) ## ✅ Checklist - [x] I have reviewed my changes to ensure they meet the project standards. - [x] I have tested my changes and ensured that all tests pass (`pdm run test`). - [x] I have formatted the code (`pdm run format`). - [x] I have verified that linting passes (`pdm run lint`). - [x] I have updated documentation where necessary. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved form-field handling to detect hidden-input-backed controls and automatically select their associated combobox buttons for more reliable interaction with dynamic forms. * **Tests** * Added unit tests covering hidden-input fallback: successful combobox selection, error when no associated combobox is found, and the direct-visible-combobox path. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b26e6bfc25 | chore: Update Python dependencies (#1093) |