mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-03-12 02:31:45 +01:00
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 -->
This commit is contained in:
@@ -91,6 +91,27 @@ kleinanzeigen_bot/__init__.py:
|
||||
"Expected CSRF Token not found in HTML content!": "Erwartetes CSRF-Token wurde im HTML-Inhalt nicht gefunden!"
|
||||
" -> deleting %s '%s'...": " -> lösche %s '%s'..."
|
||||
|
||||
extend_ads:
|
||||
"No ads need extension at this time.": "Keine Anzeigen müssen derzeit verlängert werden."
|
||||
"DONE: No ads extended.": "FERTIG: Keine Anzeigen verlängert."
|
||||
"DONE: Extended %s": "FERTIG: %s verlängert"
|
||||
"ad": "Anzeige"
|
||||
" -> SKIPPED: ad '%s' is not published yet": " -> ÜBERSPRUNGEN: Anzeige '%s' ist noch nicht veröffentlicht"
|
||||
" -> SKIPPED: ad '%s' (ID: %s) not found in published ads": " -> ÜBERSPRUNGEN: Anzeige '%s' (ID: %s) nicht gefunden"
|
||||
" -> SKIPPED: ad '%s' is not active (state: %s)": " -> ÜBERSPRUNGEN: Anzeige '%s' ist nicht aktiv (Status: %s)"
|
||||
" -> SKIPPED: ad '%s' has no endDate in API response": " -> ÜBERSPRUNGEN: Anzeige '%s' hat kein Ablaufdatum in API-Antwort"
|
||||
" -> ad '%s' expires in %d days, will extend": " -> Anzeige '%s' läuft in %d Tagen ab, wird verlängert"
|
||||
" -> SKIPPED: ad '%s' expires in %d days (can only extend within 8 days)": " -> ÜBERSPRUNGEN: Anzeige '%s' läuft in %d Tagen ab (Verlängern nur innerhalb von 8 Tagen möglich)"
|
||||
"Processing %s/%s: '%s' from [%s]...": "Verarbeite %s/%s: '%s' aus [%s]..."
|
||||
|
||||
extend_ad:
|
||||
"Extending ad '%s' (ID: %s)...": "Verlängere Anzeige '%s' (ID: %s)..."
|
||||
" -> FAILED: Could not find extend button for ad ID %s": " -> FEHLER: 'Verlängern'-Button für Anzeigen-ID %s nicht gefunden"
|
||||
" -> No confirmation dialog found, extension may have completed directly": " -> Kein Bestätigungsdialog gefunden"
|
||||
" -> SUCCESS: ad extended with ID %s": " -> ERFOLG: Anzeige mit ID %s verlängert"
|
||||
" -> FAILED: Timeout while extending ad '%s': %s": " -> FEHLER: Zeitüberschreitung beim Verlängern der Anzeige '%s': %s"
|
||||
" -> FAILED: Could not persist extension for ad '%s': %s": " -> FEHLER: Verlängerung der Anzeige '%s' konnte nicht gespeichert werden: %s"
|
||||
|
||||
publish_ads:
|
||||
"Processing %s/%s: '%s' from [%s]...": "Verarbeite %s/%s: '%s' von [%s]..."
|
||||
"Skipping because ad is reserved": "Überspringen, da Anzeige reserviert ist"
|
||||
@@ -183,6 +204,8 @@ kleinanzeigen_bot/__init__.py:
|
||||
"DONE: No new/outdated ads found.": "FERTIG: Keine neuen/veralteten Anzeigen gefunden."
|
||||
"DONE: No ads to delete found.": "FERTIG: Keine zu löschenden Anzeigen gefunden."
|
||||
"DONE: No changed ads found.": "FERTIG: Keine geänderten Anzeigen gefunden."
|
||||
"Extending all ads within 8-day window...": "Verlängere alle Anzeigen innerhalb des 8-Tage-Zeitfensters..."
|
||||
"DONE: No ads found to extend.": "FERTIG: Keine Anzeigen zum Verlängern gefunden."
|
||||
"You provided no ads selector. Defaulting to \"new\".": "Es wurden keine Anzeigen-Selektor angegeben. Es wird \"new\" verwendet."
|
||||
"You provided no ads selector. Defaulting to \"changed\".": "Es wurden keine Anzeigen-Selektor angegeben. Es wird \"changed\" verwendet."
|
||||
"Unknown command: %s": "Unbekannter Befehl: %s"
|
||||
|
||||
Reference in New Issue
Block a user