Skip to content

Conversation

@1cu
Copy link
Contributor

@1cu 1cu commented Jan 17, 2026

ℹ️ Description

📋 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:

  • 🐞 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:

  • I have reviewed my changes to ensure they meet the project's standards.
  • I have tested my changes and ensured that all tests pass (pdm run test).
  • I have formatted the code (pdm run format).
  • 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.

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.

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

@github-actions github-actions bot added the bug Something isn't working label Jan 17, 2026
@codecov
Copy link

codecov bot commented Jan 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.58%. Comparing base (183c010) to head (7b38b87).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #771   +/-   ##
=======================================
  Coverage   88.58%   88.58%           
=======================================
  Files          20       20           
  Lines        2172     2173    +1     
  Branches      423      423           
=======================================
+ Hits         1924     1925    +1     
  Misses        120      120           
  Partials      128      128           
Flag Coverage Δ
integration-tests 30.23% <100.00%> (+0.03%) ⬆️
smoke-tests 32.21% <100.00%> (+0.03%) ⬆️
unit-tests 88.49% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/kleinanzeigen_bot/model/config_model.py 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 183c010...7b38b87. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai
Copy link

coderabbitai bot commented Jan 17, 2026

📝 Walkthrough

Walkthrough

Centralizes contact-field handling in KleinanzeigenBot by adding a private async method __set_contact_fields(contact: Contact), updates publish_ad() to use it, skips saved ads without id in download_ads(), exports Contact, adds optional ContactDefaults.location, and updates README shipping-type guidance.

Changes

Cohort / File(s) Summary
Contact Field Refactoring
src/kleinanzeigen_bot/__init__.py
Added private async method __set_contact_fields(self, contact: Contact) -> None to consolidate zipcode, location/city, street, name, and phone population. publish_ad() now delegates to this helper. City matching now trims whitespace and handles "City - District" variants. download_ads() collects saved IDs from ad[1].id and skips entries without id (debug log). Added Contact to public imports.
Configuration Model Enhancement
src/kleinanzeigen_bot/model/config_model.py
Added optional field `location: str
Documentation Update
README.md
Updated ad configuration docs: changed condition for sell_directly to depend on shipping_type being SHIPPING (not shipping_options) and clarified shipping_costs purpose and examples.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #763: Modifies publish_ad() ordering for category/title processing; may interact with the refactored contact handling.
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main changes: hardening contact field publishing and improving download stability when ads lack IDs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/kleinanzeigen_bot/__init__.py`:
- Around line 1129-1133: The wait is using self.web_sleep(1) but web_sleep
expects milliseconds, so it's only pausing ~1ms and the city dropdown won't
populate; update the call in the block that checks contact.location to use a
realistic millisecond delay (e.g., self.web_sleep(1000)) or replace with a short
retry loop that calls web_find_all(By.CSS_SELECTOR, "#pstad-citychsr option")
until options length is >1 with small web_sleep intervals to robustly wait for
the dropdown to populate.
- Around line 1149-1163: The contact name/street DOM interactions can raise
TimeoutError and currently may abort publishing; wrap the calls around
web_check/web_click/web_sleep/web_input for the "pstad-street" logic and the
web_check/web_input for "postad-contactname" in try/except blocks that catch
TimeoutError and either log/skip the field or re-raise with contextual message;
specifically modify the section that uses contact.street, web_check(By.ID,
"pstad-street", Is.DISABLED), web_click("addressVisibility"), web_sleep(),
web_input("pstad-street") and the section that checks postad-contactname
(web_check(By.ID, "postad-contactname", Is.READONLY) and
web_input("postad-contactname")) to handle TimeoutError consistently (e.g., log
a warning including which field failed and continue publishing or raise a new
TimeoutError with added context).
- Around line 1559-1564: The debug message logged when skipping a saved ad
without an id (inside the loop over ads where LOG.debug("Skipping saved ad
without id: %s", ad[0]) is called) must be localized; replace the literal string
with a call to the project's translation helper (e.g. _("Skipping saved ad
without id: %s") or gettext.gettext(...)) and ensure the translation function is
imported/available in this module so the LOG.debug call uses the translated
string while keeping the placeholder and ad[0] argument intact; keep the
surrounding logic (saved_ad_id check, continue, saved_ad_ids.append) unchanged.

In `@src/kleinanzeigen_bot/model/config_model.py`:
- Around line 66-70: The new Pydantic field "location" in config_model.py lacks
Field metadata; update the "location: str | None = None" declaration to include
a Field(...) with a concise description and an example (e.g., description="City
or locality of the listing", example="Berlin") to keep schema docs consistent,
and ensure Field is imported from pydantic at the top if not already present;
modify the declaration in the class where "name", "street", "zipcode",
"location", "phone" are defined (look for the attribute named location) to use
Field for the default instead of a bare None.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/kleinanzeigen_bot/__init__.py (1)

15-26: Use absolute imports for project modules.

The new Contact import keeps the relative style; project guidelines require absolute imports for project modules. Consider switching this local import block to absolute paths for consistency.

♻️ Proposed update
-from . import extract, resources
-from ._version import __version__
-from .model.ad_model import MAX_DESCRIPTION_LENGTH, Ad, AdPartial, Contact, calculate_auto_price
-from .model.config_model import Config
-from .update_checker import UpdateChecker
-from .utils import dicts, error_handlers, loggers, misc
-from .utils.exceptions import CaptchaEncountered
-from .utils.files import abspath
-from .utils.i18n import Locale, get_current_locale, pluralize, set_current_locale
-from .utils.misc import ainput, ensure, is_frozen
-from .utils.web_scraping_mixin import By, Element, Is, WebScrapingMixin
+from kleinanzeigen_bot import extract, resources
+from kleinanzeigen_bot._version import __version__
+from kleinanzeigen_bot.model.ad_model import MAX_DESCRIPTION_LENGTH, Ad, AdPartial, Contact, calculate_auto_price
+from kleinanzeigen_bot.model.config_model import Config
+from kleinanzeigen_bot.update_checker import UpdateChecker
+from kleinanzeigen_bot.utils import dicts, error_handlers, loggers, misc
+from kleinanzeigen_bot.utils.exceptions import CaptchaEncountered
+from kleinanzeigen_bot.utils.files import abspath
+from kleinanzeigen_bot.utils.i18n import Locale, get_current_locale, pluralize, set_current_locale
+from kleinanzeigen_bot.utils.misc import ainput, ensure, is_frozen
+from kleinanzeigen_bot.utils.web_scraping_mixin import By, Element, Is, WebScrapingMixin

As per coding guidelines, please use absolute imports for project modules.

🤖 Fix all issues with AI agents
In `@src/kleinanzeigen_bot/__init__.py`:
- Around line 1119-1127: The ZIP input sequence can raise a TimeoutError from
web_input and currently would abort publishing; update the block that handles
contact.zipcode (using web_find and web_input for By.ID "pstad-zip") to catch
TimeoutError around the web_input call, log a concise warning (including contact
identifier/context) and skip continuing ZIP entry instead of letting the
exception bubble; keep the existing fallback for clear_input but ensure both the
clear and the subsequent web_input are guarded so any TimeoutError is caught and
handled gracefully.
♻️ Duplicate comments (2)
src/kleinanzeigen_bot/__init__.py (2)

1129-1133: Increase web_sleep delay for city dropdown.

Already flagged in a prior review: web_sleep expects milliseconds; 1 is ~1ms and too short for the dropdown to populate.


1149-1163: Guard street/name web operations with TimeoutError handling.

Already flagged in a prior review; missing handling can abort publishing on DOM variants.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/kleinanzeigen_bot/__init__.py`:
- Around line 1134-1148: The current loop in the contact location selection
(inside the block using self.web_find_all and self.web_select) swallows the case
where no option matches contact.location; add a boolean flag (e.g., found =
False) before iterating options, set found = True when you call self.web_select,
and after the loop (still inside the try) if found is False emit a LOG.warning
(or LOG.info) noting that no dropdown option matched contact.location so the
location was ignored; keep the existing TimeoutError except block unchanged.
- Around line 1121-1127: The guard checking for None after calling self.web_find
is redundant because web_find either returns an Element or raises TimeoutError;
update the try block in the initialization flow to call await
zip_field.clear_input() directly after zip_field = await self.web_find(By.ID,
"pstad-zip") and remove the if zip_field is not None: conditional, keeping the
existing TimeoutError except block intact; refer to the zip_field variable and
the self.web_find(By.ID, "pstad-zip") call to locate the change.

@1cu 1cu requested a review from sebthom January 17, 2026 23:53
sebthom
sebthom previously approved these changes Jan 18, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/kleinanzeigen_bot/__init__.py`:
- Line 17: Replace the relative import in __init__.py with an absolute import:
update the statement that currently imports MAX_DESCRIPTION_LENGTH, Ad,
AdPartial, Contact, calculate_auto_price from .model.ad_model to import them
using the package name (e.g., kleinanzeigen_bot.model.ad_model) so the symbols
MAX_DESCRIPTION_LENGTH, Ad, AdPartial, Contact, and calculate_auto_price are
imported via an absolute path.

@1cu 1cu requested a review from sebthom January 18, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Development

Successfully merging this pull request may close these issues.

3 participants