Commit Graph

75 Commits

Author SHA1 Message Date
Jens
b4cb979164 fix: auth probe + diagnostics for UNKNOWN states (#791) 2026-01-28 06:08:45 +01:00
Jens
eda1b4d0ec feat: add browser profile XDG support and documentation (#777) 2026-01-23 22:45:22 +01:00
Jens
15f35ba3ee fix: publishing contact fields and download stability (#771)
## ℹ️ Description
- Link to the related issue(s): Issue #761
- Describe the motivation and context for this change.
- This PR bundles several small fixes identified during recent testing,
covering issue #761 and related publishing/download edge cases.

## 📋 Changes Summary
- Avoid crashes in `download --ads=new` when existing local ads lack an
ID; skip those files for the “already downloaded” set and log a clear
reason.
- Harden publishing contact fields: clear ZIP before typing; tolerate
missing phone field; handle missing street/name/ZIP/location gracefully
with warnings instead of aborting.
- Improve location selection by matching full option text or the
district suffix after ` - `.
- Preserve `contact.location` in defaults (config model + regenerated
schema with example).

### ⚙️ Type of Change
Select the type(s) of change(s) included in this pull request:
- [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

## Release Notes

* **New Features**
* Added optional location field to contact configuration for specifying
city/locality details in listings.
* Enhanced contact field validation with improved error handling and
fallback mechanisms.

* **Bug Fixes**
* Ad download process now gracefully handles unpublished or manually
created ads instead of failing.

* **Documentation**
* Clarified shipping type requirements and cost configuration guidance
in README.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-19 15:39:11 +01:00
Jens
6ef6aea3a8 feat: Add extend command to extend ads before expiry (#732)
## ℹ️ Description

Add a manual "extend" command to extend listings shortly before they
expire. This keeps existing watchers/savers and does not count toward
the current 100 ads/month quota.

- Link to the related issue(s): Issue #664
- **Motivation**: Users need a way to extend ads before they expire
without republishing (which consumes quota).

## 📋 Changes Summary

### Implementation
- Add `extend` command case in `run()`
- Implement `extend_ads()` to filter and process eligible ads
- Implement `extend_ad()` for browser automation
- Add German translations for all user-facing messages

### Testing
- Tests cover: filtering logic, date parsing, browser automation, error
handling, edge cases

### Features
- Detects ads within the **8-day extension window** (kleinanzeigen.de
policy)
- Uses API `endDate` from `/m-meine-anzeigen-verwalten.json` for
eligibility
- Only extends active ads (`state == "active"`)
- Handles confirmation dialog (close dialog / skip paid bump-up)
- Updates `updated_on` in YAML after successful extension
- Supports `--ads` parameter to extend specific ad IDs

### Usage
```bash
kleinanzeigen-bot extend                  # Extend all eligible ads
kleinanzeigen-bot extend --ads=1,2,3      # Extend specific ads
```

### ⚙️ 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 updated documentation where necessary (help text in English
+ German).

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**
* Added an "extend" command to find ads nearing expiry (default 8-day
window) or target specific IDs, open a session, attempt extensions, and
record per-ad outcomes.

* **Documentation**
* Updated CLI/help (bilingual) and README to document the extend
command, options (--ads), default behavior, and expiry-window
limitations.

* **Tests**
* Added comprehensive unit tests for eligibility rules, date parsing
(including German format), edge cases, UI interaction flows, timing, and
error handling.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-19 10:24:23 +01:00
Jens
920ddf5533 feat: Add automatic price reduction on reposts (#691) 2025-12-17 20:31:58 +01:00
Jens
25079c32c0 fix: increase login detection timeout to fix intermittent failures (#701) (#726)
## ℹ️ Description

This PR fixes intermittent login detection failures where the bot fails
to detect existing login sessions and unnecessarily re-logins,
potentially causing IP blocks.

- Link to the related issue(s): Issue #701
- Describe the motivation and context for this change:

Users reported that the bot sometimes fails to detect existing login
sessions (50/50 behavior), especially for browser profiles that haven't
been used for 20+ days. This appears to be a race condition where:
1. `web_open()` completes when `document.readyState == 'complete'`
2. But kleinanzeigen.de's client-side JavaScript hasn't yet rendered
user profile elements
3. The login detection timeout (5s default) is too short for slow
networks or sessions requiring server-side validation

## 📋 Changes Summary

- **Add dedicated `login_detection` timeout** to `TimeoutConfig`
(default: 10s, previously used generic 5s timeout)
- **Apply timeout to both DOM checks** in `is_logged_in()`: `.mr-medium`
and `#user-email` elements
- **Add debug logging** to track which element detected login or if no
login was found
- **Regenerate JSON schema** to include new timeout configuration
- **Effective total timeout**: ~22.5s (10s base × 1.0 multiplier × 1.5
backoff × 2 retries) vs previous ~11.25s

### Benefits:
- Addresses race condition between page load completion and client-side
rendering
- Provides sufficient time for sessions requiring server-side validation
(20+ days old)
- User-configurable via `timeouts.login_detection` in `config.yaml`
- Follows established pattern of dedicated timeouts (`sms_verification`,
`gdpr_prompt`, etc.)

### ⚙️ 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**
* Added a configurable login-detection timeout (default 10s, min 1s) to
tune session detection.

* **Bug Fixes**
* More reliable login checks using a timeout-aware, two-step detection
sequence.
* Improved diagnostic logging for login attempts, retry behavior,
detection outcomes, and timeout events.

* **Documentation**
* Added troubleshooting guidance explaining the login-detection timeout
and when to adjust it.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-16 21:30:40 +01:00
Jens
9ed87ff17f fix: wait for image upload completion before submitting ad (#716)
## ℹ️ Description
Fixes a race condition where ads were submitted before all images
finished uploading to the server, causing some images to be missing from
published ads.

- Link to the related issue(s): Issue #715
- The bot was submitting ads immediately after the last image
`send_file()` call completed, only waiting 1-2.5 seconds via
`web_sleep()`. This wasn't enough time for server-side image processing,
thumbnail generation, and DOM updates to complete, resulting in missing
images in published ads.

## 📋 Changes Summary

### Image Upload Verification (Initial Fix)
- Added thumbnail verification in `__upload_images()` method to wait for
all image thumbnails to appear in the DOM after upload
- Added configurable timeout `image_upload` to `TimeoutConfig` (default:
30s, minimum: 5s)
- Improved error messages to show expected vs actual image count when
upload times out
- Added German translations for new log messages and error messages
- Regenerated JSON schemas to include new timeout configuration

### Polling Performance & Crash Fix (Follow-up Fix)
- Fixed critical bug where `web_find_all()` would raise `TimeoutError`
when no thumbnails exist yet, causing immediate crash
- Wrapped DOM queries in `try/except TimeoutError` blocks to handle
empty results gracefully
- Changed polling to use `self._timeout("quick_dom")` (~1s with PR #718)
instead of default timeout
- Improved polling performance: reduced cycle time from ~2s to ~1.5s
- DOM queries are client-side only (no server load from frequent
polling)

**New configuration option:**
```yaml
timeouts:
  image_upload: 30.0  # Total timeout for image upload and server-side processing
  quick_dom: 1.0      # Per-poll timeout for thumbnail checks (adjustable via multiplier)
```

The bot now polls the DOM for `ul#j-pictureupload-thumbnails >
li.ui-sortable-handle` elements after uploading images, ensuring
server-side processing is complete before submitting the ad form.

### ⚙️ 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

* **New Features**
* Image uploads now verify completion by waiting for all uploaded
thumbnails to appear before proceeding.

* **Improvements**
  * Added a configurable image upload timeout (default 30s, minimum 5s).
* Improved timeout reporting: when thumbnails don’t appear in time, the
app returns clearer feedback showing expected vs. observed counts.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-10 14:04:42 +01:00
Jens
6cbc25b54c docs: Improve README clarity and fix configuration documentation (#711)
## ℹ️ Description

This PR addresses issue #708 by improving the README's About section to
make the bot's purpose clearer to new users. It also fixes a technical
inaccuracy in the configuration documentation.

- Link to the related issue(s): Issue #708
- **Motivation**: The current About section uses ambiguous terminology
("ads" instead of "listings") and doesn't clearly communicate what the
bot does. Additionally, the configuration example incorrectly documents
`shipping_costs` as available in `ad_defaults`, when it's only
implemented for per-ad configuration.

## 📋 Changes Summary

**About Section Improvements:**
- Changed "ads" to "listings" for clarity (addresses confusion mentioned
in #708)
- Added "Key Features" section with 6 concrete capabilities
- Added "Why This Project?" section explaining the rewrite and
differences from legacy client
- Preserved all legal disclaimers

**Configuration Documentation Fix:**
- Removed `shipping_costs` from `ad_defaults` example (not implemented
in `AdDefaults` Pydantic class)
- Added clarifying comment that `shipping_costs` and `shipping_options`
must be configured per-ad
- Verified `shipping_costs` remains documented in ad configuration
section

### ⚙️ 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)

*Note: This is a documentation-only change with no code modifications.*

##  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 (N/A -
documentation only).
- [x] I have formatted the code (N/A - documentation only).
- [x] I have verified that linting passes (N/A - documentation only).
- [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.
2025-12-05 20:51:48 +01:00
Jens
a3ac27c441 feat: add configurable timeouts (#673)
## ℹ️ Description
- Related issues: #671, #658
- Introduces configurable timeout controls plus retry/backoff handling
for flaky DOM operations.

We often see timeouts which are note reproducible in certain
configurations. I suspect timeout issues based on a combination of
internet speed, browser, os, age of the computer and the weather.

This PR introduces a comprehensive config model to tweak timeouts.

## 📋 Changes Summary
- add TimeoutConfig to the main config/schema and expose timeouts in
README/docs
- wire WebScrapingMixin, extractor, update checker, and browser
diagnostics to honor the configurable timeouts and retries
- update translations/tests to cover the new behaviour and ensure
lint/mypy/pyright pipelines remain green

### ⚙️ 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

* **New Features**
* Centralized, configurable timeout system for web interactions,
detection flows, publishing, and pagination.
* Optional retry with exponential backoff for operations that time out.

* **Improvements**
* Replaced fixed wait times with dynamic timeouts throughout workflows.
  * More informative timeout-related messages and diagnostics.

* **Tests**
* New and expanded test coverage for timeout behavior, pagination,
diagnostics, and retry logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-13 15:08:52 +01:00
Jens Bergmann
332926519d feat: chrome version detection clean (#607) 2025-08-18 13:19:50 +02:00
Jens Bergmann
c9d04da70d feat: browser connection improvements (#601) 2025-08-13 09:29:25 +02:00
Jens Bergmann
91a40b0116 feat: enhanced folder naming (#599) 2025-08-12 10:43:26 +02:00
Jens Bergmann
c425193b10 feat: add create-config subcommand to generate default config (#577) 2025-07-13 13:09:40 +02:00
Jens Bergmann
1a1633e12d feat: introduce smoke test group and fail-fast test orchestration (#572) 2025-07-09 19:23:52 +02:00
Jens Bergmann
7ff005d18b fix: chores (#565) 2025-07-03 15:12:43 +02:00
Jens Bergmann
5430f5cdc6 feat: update check (#561)
feat(update-check): add robust update check with interval support, state management, and CLI integration

- Implement version and interval-based update checks with configurable settings
- Add CLI command `kleinanzeigen-bot update-check` for manual checks
- Introduce state file with versioning, UTC timestamps, and migration logic
- Validate and normalize intervals (1d–4w) with fallback for invalid values
- Ensure correct handling of timezones and elapsed checks
- Improve error handling, logging, and internationalization (i18n)
- Add comprehensive test coverage for config, interval logic, migration, and CLI
- Align default config, translations, and schema with new functionality
- Improve help command UX by avoiding config/log loading for `--help`
- Update documentation and README with full feature overview
2025-06-27 07:52:40 +02:00
Heavenfighter
f69ebef643 feat: add new update command to update published ads (#549)
Co-authored-by: Jens Bergmann <1742418+1cu@users.noreply.github.com>
2025-06-16 11:46:51 +02:00
sebthom
23910ffbf5 ci: publish code coverage reports 2025-05-15 22:13:38 +02:00
sebthom
6ede14596d feat: add type safe Ad model 2025-05-15 12:07:49 +02:00
sebthom
1369da1c34 feat: add type safe Config model 2025-05-15 12:07:49 +02:00
sebthom
f2e6f0b20b chore: update pyproject.toml 2025-05-12 14:08:50 +02:00
Airwave1981
d87ae6e740 feat: allow auto-restart on captcha (#481)
Co-authored-by: sebthom <sebthom@users.noreply.github.com>
2025-04-26 14:40:47 +02:00
Jens Bergmann
772326003f fix: Separate 'changed' and 'due' ad selectors (#442)
This commit implements a new 'changed' selector for the --ads option that
publishes only ads that have been modified since their last publication.
The 'due' selector now only republishes ads based on the time interval,
without considering content changes.

The implementation allows combining selectors with commas (e.g., --ads=changed,due)
to publish both changed and due ads. Documentation and translations have been
updated accordingly.

Fixes #411
2025-02-28 14:53:53 -05:00
sebthom
9f19cd85bd docs: fix build status badge 2025-02-12 21:40:45 +01:00
Jens Bergmann
4051620aed enh: allow per-ad overriding of global description affixes (#416) 2025-02-11 23:39:26 +01:00
sebthom
e8d342dc68 docs: document ad config defaults 2025-02-10 03:23:33 +01:00
sebthom
08197eabae docs: improve disclaimer 2025-02-03 22:06:30 +01:00
1cu
f01109c956 feat: add hash-based ad change detection (#343) (#388)
Co-authored-by: sebthom <sebthom@users.noreply.github.com>
2025-01-26 23:37:33 +01:00
sebthom
3d27755207 docs: update README 2025-01-26 20:05:28 +01:00
sebthom
7d9b857a46 docs: Update doc 2025-01-20 21:40:28 +01:00
Heavenfighter
ca876e628b fix shipping options when downloading. Fixes #375 (#376) 2025-01-10 16:05:11 +01:00
sebthom
1e782beabc fix: update help text 2024-12-27 13:49:05 +01:00
sebthom
9d54a949e7 feat: add multi-language support 2024-12-27 13:04:30 +01:00
sebthom
a738f0748d docs: add related OSS projects section 2024-12-22 22:19:44 +01:00
sebthom
a876add5a7 feat: by default delete old ads after republishing #338 2024-11-22 12:41:34 +01:00
sebthom
f9fdf4d158 refact: update categories 2024-11-22 12:40:27 +01:00
Moritz Graf
b3cc8ef5cd Fixing missing src directory in README (#288) 2024-04-01 18:09:50 +02:00
sebthom
e7c7ba90be support re-using already open browser window 2024-03-07 23:07:23 +01:00
sebthom
a441c5de73 replace selenium with nodriver 2024-03-07 20:33:23 +01:00
sebthom
3a52f7f629 update doc 2024-01-12 11:37:40 +01:00
sebthom
b723e59ac4 update kleinanzeigen URL 2023-05-15 21:45:57 +02:00
Jeppy
70868395b2 FIX typo 2023-02-25 12:04:34 +01:00
Philipp K
886d812393 FIX Download path not found 2022-12-18 20:11:57 +01:00
Jeppy
45fd4bac9f ADD download shipping options and sell directly
LIMITATION extracts only the cheapest shipping option
2022-12-12 13:18:00 +01:00
Jeppy
e483c003d0 ADD ability to select shipping packages and sell directly 2022-12-12 13:18:00 +01:00
PhilK-7
70a23dbcc7 ADD download --all feature (#139) 2022-11-22 18:52:32 +01:00
PhilK-7
5321b7cd12 Add download command. Fixes #32 (#114) 2022-10-25 22:27:10 +02:00
Peter Simon
728d2cd888 Executable bit for user needs 755 2022-10-03 10:32:32 +02:00
sebthom
1e3c0bee24 add code of conduct 2022-08-21 20:29:55 +02:00
sebthom
f924ed89d0 Support extended glob patterns 2022-06-11 18:55:13 +02:00