1044 Commits

Author SHA1 Message Date
kleinanzeigen-bot-tu[bot]
09c1be8802 chore: ✔ Update setuptools 82.0.1 -> 83.0.0 (#1205)
✔ Update setuptools 82.0.1 -> 83.0.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
latest preview
2026-07-06 22:10:17 +02:00
dependabot[bot]
dd58089813 ci(deps): bump the all-actions group with 3 updates (#1207)
Bumps the all-actions group with 3 updates:
[docker/setup-buildx-action](https://github.com/docker/setup-buildx-action),
[github/codeql-action/init](https://github.com/github/codeql-action) and
[github/codeql-action/analyze](https://github.com/github/codeql-action).

Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/setup-buildx-action/releases">docker/setup-buildx-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.2.0</h2>
<ul>
<li>Preserve names in esbuild bundle by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/572">docker/setup-buildx-action#572</a></li>
<li>Bump <code>@​actions/core</code> from 3.0.0 to 3.0.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/551">docker/setup-buildx-action#551</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.90.0 to 0.92.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/557">docker/setup-buildx-action#557</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/580">docker/setup-buildx-action#580</a></li>
<li>Bump <code>@​sigstore/core</code> from 3.1.0 to 3.2.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/573">docker/setup-buildx-action#573</a></li>
<li>Bump <code>@​sigstore/verify</code> from 3.1.0 to 3.1.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/576">docker/setup-buildx-action#576</a></li>
<li>Bump js-yaml from 4.1.1 to 5.2.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/562">docker/setup-buildx-action#562</a></li>
<li>Bump sigstore from 4.1.0 to 4.1.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/577">docker/setup-buildx-action#577</a></li>
<li>Bump tmp from 0.2.5 to 0.2.7 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/556">docker/setup-buildx-action#556</a></li>
<li>Bump undici from 6.25.0 to 6.27.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/570">docker/setup-buildx-action#570</a></li>
<li>Bump vite from 7.3.2 to 7.3.6 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/569">docker/setup-buildx-action#569</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v4.1.0...v4.2.0">https://github.com/docker/setup-buildx-action/compare/v4.1.0...v4.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bb05f3f551"><code>bb05f3f</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/580">#580</a>
from docker/dependabot/npm_and_yarn/docker/actions-to...</li>
<li><a
href="321c814cb5"><code>321c814</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="b9a36ef79b"><code>b9a36ef</code></a>
build(deps): bump <code>@​docker/actions-toolkit</code> from 0.91.0 to
0.92.0</li>
<li><a
href="ebeab24128"><code>ebeab24</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/570">#570</a>
from docker/dependabot/npm_and_yarn/undici-6.27.0</li>
<li><a
href="5c7b8ae78c"><code>5c7b8ae</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="037e618cd9"><code>037e618</code></a>
build(deps): bump undici from 6.25.0 to 6.27.0</li>
<li><a
href="66080e5802"><code>66080e5</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/577">#577</a>
from docker/dependabot/npm_and_yarn/sigstore-4.1.1</li>
<li><a
href="409aef0aa3"><code>409aef0</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/562">#562</a>
from docker/dependabot/npm_and_yarn/js-yaml-4.2.0</li>
<li><a
href="49c6e42949"><code>49c6e42</code></a>
build(deps): bump sigstore from 4.1.0 to 4.1.1</li>
<li><a
href="2211273e81"><code>2211273</code></a>
[dependabot skip] chore: update generated content</li>
<li>Additional commits viewable in <a
href="d7f5e7f509...bb05f3f551">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action/init` from 4.36.2 to 4.36.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/init's
releases</a>.</em></p>
<blockquote>
<h2>v4.36.3</h2>
<p>No user facing changes.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/init's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.36.3 - 01 Jul 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.2 - 04 Jun 2026</h2>
<ul>
<li>Cache CodeQL CLI version information across Actions steps. <a
href="https://redirect.github.com/github/codeql-action/pull/3943">#3943</a></li>
<li>Reduce requests while waiting for analysis processing by using
exponential backoff when polling SARIF processing status. <a
href="https://redirect.github.com/github/codeql-action/pull/3937">#3937</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6">2.25.6</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3948">#3948</a></li>
</ul>
<h2>4.36.1 - 02 Jun 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.0 - 22 May 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.19.4. <a
href="https://redirect.github.com/github/codeql-action/pull/3894">#3894</a></li>
<li>Add support for SHA-256 Git object IDs. <a
href="https://redirect.github.com/github/codeql-action/pull/3893">#3893</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5">2.25.5</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3926">#3926</a></li>
</ul>
<h2>4.35.5 - 15 May 2026</h2>
<ul>
<li>We have improved how the JavaScript bundles for the CodeQL Action
are generated to avoid duplication across bundles and reduce the size of
the repository by around 70%. This should have no effect on the runtime
behaviour of the CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3899">#3899</a></li>
<li>For performance and accuracy reasons, <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> will now only be enabled on a pull request when
diff-informed analysis is also enabled for that run. If diff-informed
analysis is unavailable (for example, because the PR diff ranges could
not be computed), the action will fall back to a full analysis. <a
href="https://redirect.github.com/github/codeql-action/pull/3791">#3791</a></li>
<li>If multiple inputs are provided for the GitHub-internal
<code>analysis-kinds</code> input, only <code>code-scanning</code> will
be enabled. The <code>analysis-kinds</code> input is experimental, for
GitHub-internal use only, and may change without notice at any time. <a
href="https://redirect.github.com/github/codeql-action/pull/3892">#3892</a></li>
<li>Added an experimental change which, when running a Code Scanning
analysis for a PR with <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> enabled, prefers CodeQL CLI versions that have
a cached overlay-base database for the configured languages. This speeds
up analysis for a repository when there is not yet a cached overlay-base
database for the latest CLI version. We expect to roll this change out
to everyone in May. <a
href="https://redirect.github.com/github/codeql-action/pull/3880">#3880</a></li>
</ul>
<h2>4.35.4 - 07 May 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4">2.25.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3881">#3881</a></li>
</ul>
<h2>4.35.3 - 01 May 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: Add a deprecation warning for
customers using CodeQL version 2.19.3 and earlier. These versions of
CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise
Server 3.15, and will be unsupported by the next minor release of the
CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3837">#3837</a></li>
<li>Configurations for private registries that use Cloudsmith or GCP
OIDC are now accepted. <a
href="https://redirect.github.com/github/codeql-action/pull/3850">#3850</a></li>
<li>Best-effort connection tests for private registries now use
<code>GET</code> requests instead of <code>HEAD</code> for better
compatibility with various registry implementations. For NuGet feeds,
the test is now always performed against the service index. <a
href="https://redirect.github.com/github/codeql-action/pull/3853">#3853</a></li>
<li>Fixed a bug where two diagnostics produced within the same
millisecond could overwrite each other on disk, causing one of them to
be lost. <a
href="https://redirect.github.com/github/codeql-action/pull/3852">#3852</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3">2.25.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3865">#3865</a></li>
</ul>
<h2>4.35.2 - 15 Apr 2026</h2>
<ul>
<li>The undocumented TRAP cache cleanup feature that could be enabled
using the <code>CODEQL_ACTION_CLEANUP_TRAP_CACHES</code> environment
variable is deprecated and will be removed in May 2026. If you are
affected by this, we recommend disabling TRAP caching by passing the
<code>trap-caching: false</code> input to the <code>init</code> Action.
<a
href="https://redirect.github.com/github/codeql-action/pull/3795">#3795</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="54f647b7e1"><code>54f647b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3984">#3984</a>
from github/update-v4.36.3-1f34ec164</li>
<li><a
href="e78819e055"><code>e78819e</code></a>
Trigger checks</li>
<li><a
href="2c9d3d63eb"><code>2c9d3d6</code></a>
Update changelog for v4.36.3</li>
<li><a
href="1f34ec1643"><code>1f34ec1</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3983">#3983</a>
from github/mbg/repo-props/ff-for-config-file-prop</li>
<li><a
href="d5f0145480"><code>d5f0145</code></a>
Log when repository property has a value but is ignored</li>
<li><a
href="f27f56386a"><code>f27f563</code></a>
Add test for when the FF is off</li>
<li><a
href="0025d0f2b5"><code>0025d0f</code></a>
Use FF</li>
<li><a
href="f7fa18f05d"><code>f7fa18f</code></a>
Add FF for config file repo property</li>
<li><a
href="628fc3f124"><code>628fc3f</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3979">#3979</a>
from github/henrymercer/overlay-db-cleanup-size-tele...</li>
<li><a
href="9cfb67bab9"><code>9cfb67b</code></a>
Add clarifying comments</li>
<li>Additional commits viewable in <a
href="8aad20d150...54f647b7e1">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action/analyze` from 4.36.2 to 4.36.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/analyze's
releases</a>.</em></p>
<blockquote>
<h2>v4.36.3</h2>
<p>No user facing changes.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/analyze's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.36.3 - 01 Jul 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.2 - 04 Jun 2026</h2>
<ul>
<li>Cache CodeQL CLI version information across Actions steps. <a
href="https://redirect.github.com/github/codeql-action/pull/3943">#3943</a></li>
<li>Reduce requests while waiting for analysis processing by using
exponential backoff when polling SARIF processing status. <a
href="https://redirect.github.com/github/codeql-action/pull/3937">#3937</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6">2.25.6</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3948">#3948</a></li>
</ul>
<h2>4.36.1 - 02 Jun 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.0 - 22 May 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.19.4. <a
href="https://redirect.github.com/github/codeql-action/pull/3894">#3894</a></li>
<li>Add support for SHA-256 Git object IDs. <a
href="https://redirect.github.com/github/codeql-action/pull/3893">#3893</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5">2.25.5</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3926">#3926</a></li>
</ul>
<h2>4.35.5 - 15 May 2026</h2>
<ul>
<li>We have improved how the JavaScript bundles for the CodeQL Action
are generated to avoid duplication across bundles and reduce the size of
the repository by around 70%. This should have no effect on the runtime
behaviour of the CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3899">#3899</a></li>
<li>For performance and accuracy reasons, <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> will now only be enabled on a pull request when
diff-informed analysis is also enabled for that run. If diff-informed
analysis is unavailable (for example, because the PR diff ranges could
not be computed), the action will fall back to a full analysis. <a
href="https://redirect.github.com/github/codeql-action/pull/3791">#3791</a></li>
<li>If multiple inputs are provided for the GitHub-internal
<code>analysis-kinds</code> input, only <code>code-scanning</code> will
be enabled. The <code>analysis-kinds</code> input is experimental, for
GitHub-internal use only, and may change without notice at any time. <a
href="https://redirect.github.com/github/codeql-action/pull/3892">#3892</a></li>
<li>Added an experimental change which, when running a Code Scanning
analysis for a PR with <a
href="https://redirect.github.com/github/roadmap/issues/1158">improved
incremental analysis</a> enabled, prefers CodeQL CLI versions that have
a cached overlay-base database for the configured languages. This speeds
up analysis for a repository when there is not yet a cached overlay-base
database for the latest CLI version. We expect to roll this change out
to everyone in May. <a
href="https://redirect.github.com/github/codeql-action/pull/3880">#3880</a></li>
</ul>
<h2>4.35.4 - 07 May 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4">2.25.4</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3881">#3881</a></li>
</ul>
<h2>4.35.3 - 01 May 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: Add a deprecation warning for
customers using CodeQL version 2.19.3 and earlier. These versions of
CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise
Server 3.15, and will be unsupported by the next minor release of the
CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3837">#3837</a></li>
<li>Configurations for private registries that use Cloudsmith or GCP
OIDC are now accepted. <a
href="https://redirect.github.com/github/codeql-action/pull/3850">#3850</a></li>
<li>Best-effort connection tests for private registries now use
<code>GET</code> requests instead of <code>HEAD</code> for better
compatibility with various registry implementations. For NuGet feeds,
the test is now always performed against the service index. <a
href="https://redirect.github.com/github/codeql-action/pull/3853">#3853</a></li>
<li>Fixed a bug where two diagnostics produced within the same
millisecond could overwrite each other on disk, causing one of them to
be lost. <a
href="https://redirect.github.com/github/codeql-action/pull/3852">#3852</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3">2.25.3</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3865">#3865</a></li>
</ul>
<h2>4.35.2 - 15 Apr 2026</h2>
<ul>
<li>The undocumented TRAP cache cleanup feature that could be enabled
using the <code>CODEQL_ACTION_CLEANUP_TRAP_CACHES</code> environment
variable is deprecated and will be removed in May 2026. If you are
affected by this, we recommend disabling TRAP caching by passing the
<code>trap-caching: false</code> input to the <code>init</code> Action.
<a
href="https://redirect.github.com/github/codeql-action/pull/3795">#3795</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="54f647b7e1"><code>54f647b</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3984">#3984</a>
from github/update-v4.36.3-1f34ec164</li>
<li><a
href="e78819e055"><code>e78819e</code></a>
Trigger checks</li>
<li><a
href="2c9d3d63eb"><code>2c9d3d6</code></a>
Update changelog for v4.36.3</li>
<li><a
href="1f34ec1643"><code>1f34ec1</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3983">#3983</a>
from github/mbg/repo-props/ff-for-config-file-prop</li>
<li><a
href="d5f0145480"><code>d5f0145</code></a>
Log when repository property has a value but is ignored</li>
<li><a
href="f27f56386a"><code>f27f563</code></a>
Add test for when the FF is off</li>
<li><a
href="0025d0f2b5"><code>0025d0f</code></a>
Use FF</li>
<li><a
href="f7fa18f05d"><code>f7fa18f</code></a>
Add FF for config file repo property</li>
<li><a
href="628fc3f124"><code>628fc3f</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3979">#3979</a>
from github/henrymercer/overlay-db-cleanup-size-tele...</li>
<li><a
href="9cfb67bab9"><code>9cfb67b</code></a>
Add clarifying comments</li>
<li>Additional commits viewable in <a
href="8aad20d150...54f647b7e1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 22:09:58 +02:00
Jens
cf6662dd26 fix: require strict fetch for title cleanup (#1206)
## ℹ️ Description
- Link to the related issue(s): Issue #
- Fixes a remaining fail-closed gap in BEFORE_PUBLISH title cleanup for
ID-less ads when the published-ad list cannot be fetched completely.

## 📋 Changes Summary
- Require an additional strict published-ad fetch when BEFORE_PUBLISH
title cleanup may match by title for ID-less ads.
- Fail closed for ID-less publish candidates if strict published-ad
fetch is incomplete, before submit/delete actions.
- Keep ID-based candidates on the normal published-ad list so they can
continue safely.
- Add regression tests for strict-fetch usage and fail-closed behavior.
- Add German translations for the new log messages.

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

Validation performed locally:
- `pdm run pytest tests/unit/test_publishing_workflow.py
tests/unit/test_delete_flow.py`
- `pdm run format`
- `pdm run lint`
- `pdm run test`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Enhanced publishing workflow to use more precise “published ad” data
when title-based cleanup is enabled, improving match-and-replace
behavior.
* **Bug Fixes**
* Publishing now fails safely when strict published-ad data is
incomplete, avoiding retries and deletion actions when precision can’t
be guaranteed.
* For ads lacking a known identifier, the workflow intelligently selects
the best available published-ad list or skips with a warning when strict
data is unavailable.
* **Tests**
* Added unit test coverage for strict-vs-non-strict published-ad
fetching scenarios and fail-closed behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-05 17:04:42 +02:00
Jens
819d039b71 fix: persist created_on on first publish (#1204)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Fixes first-publish persistence so newly published ads write
`created_on` when missing.

## 📋 Changes Summary

- Capture first-publish state before writing the new ad ID.
- Persist one publication timestamp to both `updated_on` and missing
first-publish `created_on`.
- Add regression tests for first publish with an already-populated ad ID
and update preservation of existing `created_on`.
- No dependency, configuration, or generated artifact changes.

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

* **Bug Fixes**
* Improved publish timestamp handling so first-time publishes and later
updates record dates consistently.
* Preserves the original creation date when it already exists, while
keeping the last-updated time current.

* **Tests**
* Added coverage for timestamp behavior on first publish and subsequent
updates.
* Verified date values are stored in ISO-8601 format with timezone
information.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-05 00:51:25 +02:00
Jens
9cffbf6e8d fix: fail closed on persistence errors (#1203)
## ℹ️ Description

- Link to the related issue(s): No linked issue; follows the confirmed
P1 from `.slim/deepwork/p1-p2-validation.md`.
- Prevent publish/update workflows from reporting success or running
after-publish cleanup when local YAML persistence fails after a remote
submit succeeds.

## 📋 Changes Summary

- Add a non-retryable `PostPublishPersistenceError` carrying the remote
ad ID.
- Raise that error after logging post-submit local persistence failures.
- Count persistence failures as failed publish/update items and skip
post-submit confirmation / `AFTER_PUBLISH` cleanup.
- Add tests for direct persistence failure, publish cleanup-skip
behavior, and update non-retry/batch continuation.
- Add German translations for the new warnings.

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

* **Bug Fixes**
* Improved handling of post-publish save failures so they’re surfaced as
a clear error instead of being silently logged.
* Publishing and updating now stop retrying when local persistence fails
after a successful remote action, while still logging details and
capturing diagnostics.
  * Other retry behavior for existing publish issues remains unchanged.

* **Tests**
* Added and updated coverage for persistence failures, including error
propagation, logging, and workflow behavior across multiple items.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-04 23:46:01 +02:00
Jens
077c5db01b fix: prevent ambiguous title deletes (#1202)
## ℹ️ Description
- Link to the related issue(s): Issue #
- Prevent title-based deletion from deleting multiple same-title remote
ads.
- Make explicit ID deletion target only the configured ID, while ID-less
title matching now fails closed on ambiguous matches.

## 📋 Changes Summary
- Split delete selection so configured IDs are exact-ID only and title
matching is only used for ID-less ads.
- Require strict published-ad fetching when ID-less title matching may
run, so ambiguity detection uses a complete list.
- Skip ambiguous title matches before browser delete requests, ID
mutation, or after-delete cleanup.
- Added German translation for the new skip message.
- Updated config/docs/generated schema wording for
`delete_old_ads_by_title`.
- Added unit coverage for ambiguous title fail-closed behavior, exact-ID
behavior, strict fetch selection, and exact delete URLs.

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

Validation:
- `pdm run generate-schemas`
- `pdm run generate-config`
- `pdm run pytest tests/unit/test_delete_flow.py`
- `pdm run format`
- `pdm run lint`
- `pdm run test`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved old-ad deletion behavior for items without an ID, including
title-based matching only when needed.
* Made title-based deletion fail closed: ambiguous title matches are now
skipped.
* Ensured exact-ID deletions target only the specified ID and don’t
expand to same-title ads.
* Skips title-based matching for a batch when published-ad retrieval
can’t be completed, while continuing exact-ID deletions.
* **Documentation**
* Updated configuration documentation for title-based old-ad deletion to
reflect the new matching and skip behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-04 19:47:13 +02:00
Jens
25e2970ed0 feat: improve status APR report (#1201)
## ℹ️ Description

- Moves APR preview information out of verify output and into status
reporting.
- Improves status output into readable per-ad blocks with full relative
file paths and structured APR update/publish details.

## 📋 Changes Summary

- Keep verify focused on validation while preserving its full ad-loading
validation path.
- Show APR preview details in status without requiring verbose mode.
- Render status as path-first per-ad report lines with title, id,
status, APR update/publish details, and unchanged summary.
- Use structured APR detail data and translated human-readable reasons
instead of raw reason tokens.
- Remove the now-dead APR preview logger and stale translations.
- Update CLI help, README/docs, smoke tests, and focused unit tests.

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

Validation run:
- pdm run format
- pdm run lint
- pdm run test — 1467 passed, 4 skipped

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**
* `status` now shows detailed APR preview information for ads in a
clearer, per-ad layout.
* Help text and documentation now point users to `status` for APR
preview details.

* **Bug Fixes**
* `verify` no longer displays APR preview output, making its results
focused on configuration and integrity checks.
* Improved status output readability and APR detail handling for publish
and update scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-04 01:43:20 +02:00
Jens
28da3865c6 refactor: simplify humanizer behavior (#1200)
## ℹ️ Description

- Related issue(s): none.
- Simplifies the humanizer after PR #1199 by removing premature feature
surface that was either speculative or default-off, while keeping the
useful behavior: baseline pacing, typing jitter, and post-open viewport
randomization.

## 📋 Changes Summary

- Remove mouse-movement, idle-action, and long-pause humanizer
configuration and implementation.
- Keep plain click behavior plus baseline web_sleep pacing.
- Keep typing jitter default-on with bounded per-character delays.
- Keep post-open viewport resize default-on, preserving user-supplied
--window-size behavior and no launch-time bot --window-size.
- Update config defaults, generated schema/default config, German
translations, and unit tests.
- Delete the weak viewport integration test that asserted private state
instead of user-observable behavior.

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

Removed config keys: mouse_movement, idle_action_probability,
long_pause_probability, long_pause_min_ms, long_pause_max_ms.

##  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.

Validation: pdm run format && pdm run lint && pdm run test — 1468
passed, 4 skipped.

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**
* Simplified browser interactions to use direct clicks and per-character
typing more consistently.
* Updated viewport handling so browser size is applied after opening,
using screen metrics when available.
* Improved resizing behavior to skip invalid or unsupported cases
without interrupting browsing.
  * Adjusted humanization timing defaults for smoother, lighter pacing.

* **Refactor**
* Narrowed the humanization settings to focus on pacing, typing jitter,
and viewport behavior.
* Removed unused idle and movement-related behavior from the browsing
flow.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 21:52:07 +02:00
Jens
df6e308ab2 fix: resize viewport after opening page (#1199)
## ℹ️ Description

- Related issue(s): none.
- Fixes the screen-aware viewport regression by removing the temporary
pre-launch screen probe and resizing the already-open browser window
after the first kleinanzeigen.de page load.

## 📋 Changes Summary

- Remove the isolated probe browser path that could time out or appear
on a different screen.
- Open the main browser without bot-added `--window-size`, then resize
once after the first eligible kleinanzeigen.de page opens.
- Preserve user-supplied `--window-size` and skip
remote/headless/no-display or disabled randomization cases.
- Keep no-fallback behavior when screen metrics are invalid or no
configured viewport fits.
- Update viewport tests and German translations for moved log messages.

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

Validation run locally: `pdm run format && pdm run lint && pdm run test`
— 1470 passed, 4 skipped.

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**
* Automatically resizes the browser window after a page loads, using
screen-aware metrics from the current page.
* Selects from configured viewport sizes that fit the available screen
area, with bounded variation.
* Adds runtime diagnostics for viewport resize (attempted/applied),
including skip reasons and failure details.

* **Bug Fixes**
* Improves resilience when URL/metrics are missing, malformed, or don’t
include valid dimensions.
* Prevents resize for non-eligible pages and when a user-supplied window
size is present; resize now occurs before human-like actions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 19:42:29 +02:00
Jens
4c150f64a1 enh: Add screen-aware viewport sizing (#1198)
## ℹ️ Description

- Link to the related issue(s): PR #1193 follow-up
- Adds screen-aware humanization viewport selection so randomized
desktop sizes fit the available browser-reported screen area while
preserving permissive config validation.

## 📋 Changes Summary

- Add larger common desktop viewport defaults: `2560x1440`, `1920x1200`,
`1728x1117`, and `1512x982`.
- Probe browser-reported CSS-pixel screen metrics at launch time using
`window.screen.availWidth` / `window.screen.availHeight`.
- Filter configured viewport base sizes against available screen
dimensions, apply bounded jitter, and preserve explicit `--window-size`
overrides.
- Omit automatic `--window-size` when no configured size fits, screen
metrics are unavailable, the launch is headless, or no real
display/window manager is available; explicit user `--window-size`
remains preserved.
- Cache successful probe metrics and bound the probe with the
`chrome_remote_probe` timeout.
- Update generated default config and German translations.
- Add unit coverage and real-browser integration coverage for viewport
probing/filtering, headless/no-display skips, probe timeout/cache
behavior, and `create_browser_session()`.

### ⚙️ Type of Change

Select the type(s) of change(s) included in this pull request:
- [ ] 🐞 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

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**
* Browser sessions now support screen-aware viewport selection
automatically when viewport randomization is enabled.
* Expanded the default set of candidate viewport sizes used for
randomized sizing.
* **Bug Fixes**
* Viewport sizing now filters out candidates that don’t fit within the
available screen area.
  * If a window size is already specified, it’s preserved.
* **Tests**
* Added/expanded slow integration tests for screen probing and viewport
fitting.
* Expanded unit tests for viewport filtering, jittering, fallback
behavior, and probe reuse/timeout.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 16:40:17 +02:00
kleinanzeigen-bot-tu[bot]
6d29055323 chore: Update Python dependencies (#1197)
✔ Update filelock 3.29.4 -> 3.29.5 successful
  ✔ Update wcmatch 10.2 -> 10.2.1 successful
  ✔ Update coverage 7.14.3 -> 7.15.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-03 14:48:20 +02:00
Jens
a051712dc8 fix: handle portal combobox attributes (#1195)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Fixes publishing for special-attribute button comboboxes whose option
list opens via a fuller click sequence or renders outside the control
parent element.

## 📋 Changes Summary

- Dispatch mouseup and click in addition to the existing pointer/mouse
down events when opening button comboboxes.
- Add document-level listbox/menu fallback lookup for portal-rendered
combobox popups.
- Normalize option text whitespace before text fallback matching.
- Add regression coverage for the combobox JS contract and no-options
failure diagnostics.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved dropdown/combobox selection reliability, including better
support for portal-rendered menus and document-level listbox/menu
fallbacks.
* Made option matching more tolerant by normalizing whitespace and
applying consistent case handling.
* Reduced selection failures by using a more complete native interaction
sequence when opening and choosing options.
* Enhanced unit coverage to validate the injected selection script and
clearer timeout error messaging.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 14:48:00 +02:00
Jens
1bb8adc2cf feat: show filenames in status output (#1196)
## ℹ️ Description

Show the full ad filename in `pdm run app status` output so status rows
can be traced back to their source ad files.

- Link to the related issue(s): none
- Motivation: the status table currently shows ID, title, and status,
but not the source filename, which makes it harder to identify which ad
file a row came from.

## 📋 Changes Summary

- Add a filename field to status rows, populated from the relative ad
file path.
- Render a `Filename` column in the status table.
- Add the German translation for the new status table header.
- Update status rendering unit tests for the new column.
- No new dependencies or configuration 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)
- [x]  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

## Summary by CodeRabbit

* **New Features**
* Added a **Filename** column to the status table, displaying the
relative ad file path for each ad.

* **Tests**
* Updated automated tests to reflect the new table layout, verify
correct filename values, and adjust ANSI formatting checks to account
for the added column.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 14:13:52 +02:00
Jens
807633a6cc chore: remove CodeRabbit keyword ignores (#1194)
## ℹ️ Description

- Link to the related issue(s): N/A
- Remove CodeRabbit title keyword ignores so PRs with matching title
words are no longer skipped automatically.

## 📋 Changes Summary

- Removed `ignore_title_keywords` from `.coderabbit.yaml`.
- No runtime dependencies, configuration requirements, or application
behavior changes 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)
- [x] Chore / configuration maintenance

##  Checklist

Before requesting a review, confirm the following:
- [x] 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`). Not run — CodeRabbit config-only change.
- [ ] I have formatted the code (`pdm run format`). Not run — YAML line
deletion only.
- [ ] I have verified that linting passes (`pdm run lint`). Not run —
CodeRabbit config-only change.
- [x] I have updated documentation where necessary. No documentation
updates 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

* **Chores**
* Updated automated review settings so keyword-based exclusions are no
longer used.
* Review behavior now relies on existing draft and label checks, which
may result in more consistent PR review coverage.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 12:55:54 +02:00
Alexander Peltzer
89001b5080 feat: Add human-like interactions (#1193)
## ℹ️ Description

Adds configurable human-like browser interaction behavior to make
automation less mechanically deterministic while preserving the existing
publish/update workflows.

Related to #1120.

## 📋 Changes Summary

- Added `humanization` configuration for action delays, typing jitter,
thinking pauses, idle micro-actions, and randomized viewport sizes.
- Applied humanized timing and interaction behavior to relevant browser
automation paths.
- Added validation for viewport size formats and min/max timing ranges,
including German translations for user-facing validation errors.
- Hardened fallback behavior for humanized click and typing flows so
automation can continue when a lower-level interaction fails.
- Added focused unit coverage for delay edge cases, config validation,
and typing fallback behavior.
- Regenerated committed config/schema artifacts for the new settings.

## 🧪 Validation

- `pdm run pytest tests/unit/test_humanization.py
tests/unit/test_web_scraping_mixin.py`
- `pdm run ruff check src/kleinanzeigen_bot/utils/web_scraping_mixin.py
src/kleinanzeigen_bot/model/config_model.py
tests/unit/test_humanization.py`
- Live DOM probes with the PR worktree code via
`data/verify_dom_assumptions.py`:
  - `login-selectors`
  - `publish-selectors`
  - `price-type-controls`

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

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**
* Added configurable “humanization” behavior for browser automation:
optional mouse movement, per-keystroke typing jitter/delays,
probabilistic thinking pauses, idle micro-actions, and optional launch
viewport randomization.
  * Navigation timing now incorporates human-like action delays.

* **Bug Fixes**
* Improved resilience: humanized click/typing safely fall back to
standard actions when needed.
* Added stronger validation for viewport-size formatting and delay
min/max range consistency.

* **Tests**
* Added comprehensive unit coverage for humanization routing, event
dispatch, timing, fallbacks, idle/thinking behavior, viewport launch
arguments, and validation.

* **Documentation**
* Updated default configuration, configuration schema, and a related
translation message.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Jens <1742418+1cu@users.noreply.github.com>
2026-07-03 11:46:57 +02:00
kleinanzeigen-bot-tu[bot]
699a59bb25 chore: Update Python dependencies (#1190)
✔ Update typing-extensions 4.15.0 -> 4.16.0 successful
  ✔ Update pytest-rerunfailures 16.3 -> 16.4 successful
  ✔ Update ast-serialize 0.5.0 -> 0.6.0 successful
  ✔ Update librt 0.11.0 -> 0.12.0 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-03 08:45:27 +02:00
Jens
4cc35cbd9f docs: clarify download shipping inference (#1192)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Clarifies what `download` can infer for shipping options after the old
cheapest-option limitation became inaccurate.

## 📋 Changes Summary

- Replaces the outdated README limitation with the current download
shipping inference behavior.
- Documents pickup handling, `Versand möglich` without price, visible
shipping prices, inferred `shipping_options`,
`download.include_all_matching_shipping_options`, and `sell_directly`
scope.
- 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)

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

* **Documentation**
* Updated the README “download” limitations to clarify that shipping
details are inferred dynamically.
* Added a detailed explanation of how pickup vs. “Versand möglich”
listings are handled, how “shipping from” prices map to shipping costs
and options, and how direct-buy eligibility is determined.
* Documented the option to include all matching non-excluded shipping
options during download.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-01 18:25:26 +02:00
Jens
eda06334d1 docs: generate README usage section (#1191)
## ℹ️ Description

- Link to the related issue(s): N/A
- Keeps the README Usage command block in sync with the CLI help by
generating it as part of the artifact pipeline.

## 📋 Changes Summary

- Added a README Usage generator that renders normalized English CLI
help between explicit README markers.
- Added `generate-readme-commands` and wired it into
`generate-artifacts`.
- Extended generated artifact checks to detect README Usage drift
without mutating files.
- Added focused unit tests for marker replacement, locale/executable
normalization, ANSI stripping, and command coverage.
- No dependency 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)
- [x]  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**
* Kept the README “Usage” section automatically synchronized with the
app’s CLI help.
* Added a new `--preserve-local-settings` option to the CLI help output.

* **Bug Fixes**
* Improved and clarified CLI command/option descriptions (notably around
`verify`, `extend`, and `update` behavior).
* CI now fails early if the generated README “Usage” content is out of
date.

* **Documentation**
* Regenerated the README “Usage” console block to reflect the latest
help text and command details.
* Updated agent guidance to match the expanded README generation
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-01 16:36:03 +02:00
Jens
59185b8f6e docs: shorten pip-only install note (#1189)
## ℹ️ Description

- Link to the related issue(s): N/A
- Shortens the pip-only install note in the README so it is a side note
rather than prominent guidance.

## 📋 Changes Summary

- Condensed the pip-only note from a long block to two lines.
- 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.
- [ ] I have tested my changes and ensured that all tests pass (`pdm run
test`). Not run; documentation-only change.
- [ ] I have formatted the code (`pdm run format`). Not run;
documentation-only change.
- [ ] I have verified that linting passes (`pdm run lint`). Not run;
documentation-only change.
- [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.
2026-07-01 09:18:20 +02:00
kleinanzeigen-bot-tu[bot]
835e78f547 chore: Update Python dependencies (#1187)
✔ Update bracex 2.7 -> 3.0 successful
  ✔ Update wcmatch 10.1 -> 10.2 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-01 08:57:32 +02:00
Jens
f2da0355d5 fix: classify Auth0 IP range block (#1188)
## ℹ️ Description

- Link to the related issue(s): Issue #1120
- Classifies Kleinanzeigen IP-range block pages explicitly when Auth0
post-submit verification remains on the password URL.
- This makes the failure actionable without changing login/captcha
behavior or attempting to bypass the block.

## 📋 Changes Summary

- Add `IP_RANGE_BLOCKED` to post-submit Auth0 state classification when
the password-page DOM contains the Kleinanzeigen IP-range block heading.
- Keep existing classification facts such as `STILL_ON_PASSWORD_PAGE`,
so combined states remain visible.
- Keep detection scoped to the Auth0 password page and best-effort.
- Add focused unit tests for detection, gating, resilience, and
coexistence with Auth0 inline errors.
- No new dependencies, configuration changes, schema changes, or
translation updates.

### ⚙️ 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 tests/unit/test_login_flow.py tests/unit/test_translations.py`).
- [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 sign-in diagnostics to detect when login is stalled on the
password step due to an IP-range restriction.
* Added support for preserving existing login-state facts when the
IP-block page probe fails, and for correctly combining IP-block signals
with inline error states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-01 07:59:25 +02:00
Jens
ce0c5fa5b5 fix: handle DOM retry and button combobox selection (#1186)
## ℹ️ Description

- Link to the related issue(s): Issue #1184
- Fixes two publish-flow failures reported in issue #1184:
- persistent nodriver `ProtocolException(code=-32601)` could spin
forever in `web_await()` while repeatedly re-attaching the CDP session;
- special-attribute button comboboxes in the Handy & Telefon category
needed open/read/select to happen atomically in one browser execution.

## 📋 Changes Summary

- Bound `web_await()` CDP reattach retries by the configured timeout and
add a short nonzero retry delay to avoid event-loop starvation.
- Update special-attribute button-combobox selection to use one async
`web_execute()` script that opens via pointer/mouse events, discovers
options, matches API values, and clicks the selected option before the
dropdown can close.
- Add regression tests for bounded `-32601` retry behavior and atomic
button-combobox selection.
- Update the German translation for the enhanced combobox failure
message.
- Verified with the live `button-combobox` DOM probe.

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

## Validation

- `pdm run format`
- `pdm run lint`
- `pdm run test` — 1370 passed, 4 skipped
- `pdm run python data/verify_dom_assumptions.py run --yes --probe
button-combobox --report
data/.temp/dom-assumptions-issue-1184-button-combobox.json` — passed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved dropdown/combobox option selection with stronger matching and
more informative timeout/error reporting.
* Tightened CDP re-attach retry logic to strictly follow the remaining
timeout budget.
* Added a startup runtime warning if the required nodriver CDP re-attach
patch isn’t detected.

* **Documentation / Chores**
* Updated source installation guidance (pip-only users) to ensure the
nodriver patch is applied.
* Made the nodriver fix script marker-based and idempotent, including
normalization of legacy patched installs.

* **Tests**
* Expanded unit tests for combobox selection, re-attach timeout/bounds
behavior, CLI patch warning behavior, and the nodriver fix script.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 10:39:41 +02:00
kleinanzeigen-bot-tu[bot]
3d76a19c3c chore: Update Python dependencies (#1182)
✔ Update bracex 2.6 -> 2.7 successful
  ✔ Update basedpyright 1.39.8 -> 1.39.9 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-29 19:41:53 +02:00
Jens
27b47f7561 fix: capture Auth0 post-submit diagnostics (#1183)
## ℹ️ Description

- Link to the related issue(s): Issue #1120
- Capture diagnostics when Auth0 post-submit verification remains
inconclusive, so future failures include a DOM/screenshot bundle plus
classified metadata.

## 📋 Changes Summary

- Reuse existing login-detection diagnostics for the final Auth0
post-password-submit timeout.
- Add sanitized JSON metadata with `event`, `classification`, and
`page_url`.
- Keep diagnostics best-effort so capture failures do not mask the
original classified timeout.
- Add focused tests for enabled/disabled capture, privacy sanitization,
failure preservation, and diagnostics argument forwarding.
- No new configuration, schema, translation, captcha, or identifier-flow
changes.

### ⚙️ 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 tests/unit/test_login_flow.py tests/unit/test_translations.py`).
- [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 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

* **Bug Fixes**
* Improved login timeout handling with clearer error messages and safer
URL reporting.
* Added fallback diagnostics during failed post-login verification,
while preserving the original timeout if diagnostics capture fails.
  * Prevented sensitive URL parts from appearing in error reports.

* **Tests**
* Expanded coverage for login diagnostics forwarding and timeout
behavior with diagnostics enabled and disabled.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-29 10:40:04 +02:00
Jens
4acbc09fac fix: classify Auth0 post-submit uncertainty (#1181)
## ℹ️ Description

- Link to the related issue(s): Issue #1120
- Adds focused diagnostics/classification for the post-password-submit
Auth0 uncertainty path. This keeps the existing login/captcha/identifier
flow stable while making the new failure mode easier to classify from
logs.

## 📋 Changes Summary

- Classifies final post-submit uncertainty as still on the Auth0
password page, visible Auth0 error text, verification/MFA-like state, or
unknown redirect/session inconclusive state.
- Logs sanitized diagnostic context and raises clearer classified
messages while preserving the existing timeout prefix.
- Adds focused unit tests for the new classifications and snippet
sanitization.
- Updates German translations for new translatable messages.
- No new dependencies or configuration changes.

### ⚙️ 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
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 handling when transitioning after Auth0 password submission
by using safer, sanitized diagnostic URLs.
* Added clearer, classification-aware timeout messages when the next
verification step can’t be identified.
* Strengthened detection of post-Auth0 states, including inline Auth0
errors and MFA/verification prompts, with more graceful degradation on
probing failures.

* **Tests**
* Expanded unit tests for post-submit state classification, URL
sanitization, and improved timeout/error-message expectations, including
resilience to probe/URL retrieval failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-27 00:50:04 +02:00
kleinanzeigen-bot-tu[bot]
ccae35563a chore: Update Python dependencies (#1179)
✔ Update typer 0.26.7 -> 0.26.8 successful
  ✔ Update ruff 0.15.19 -> 0.15.20 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-26 21:47:46 +02:00
Jens
1c34da9298 feat: show APR status indicators (#1180)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Adds display-only APR indicators to the local status table so users
can see repost/update APR state without running publish/update flows.

## 📋 Changes Summary

- Adds optional `APR repost` and `APR update` columns to
`kleinanzeigen-bot status` when APR is effectively enabled for at least
one active ad.
- Reuses existing `evaluate_auto_price_reduction()` logic for REPLACE
and MODIFY modes; does not apply or mutate APR decisions.
- Keeps APR output plain while preserving existing status color
behavior.
- Adds German translations and unit coverage for rendering, evaluator
call modes, guardrails, and mutation safety.
- No new dependencies or configuration 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)
- [x]  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`: 1344 passed, 4 skipped).
- [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**
* Status tables now show optional APR-related columns for repost and
update pricing decisions when available.
* APR results are displayed in a compact, easy-to-read format such as
due, not due, error, or off.

* **Bug Fixes**
* Improved status table layout and spacing so translated status text
fits more reliably.
* Status summaries and row rendering now handle coloured and uncoloured
cells more consistently.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-26 15:45:28 +02:00
Jens
25a379fe67 feat: colorize status output (#1178)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Adds optional color to the `kleinanzeigen-bot status` table using the
existing Colorama dependency.
- Keeps default status behavior local/read-only and gates ANSI output
via terminal/env policy.

## 📋 Changes Summary

- Adds `utils.color.should_use_color()` with `NO_COLOR` > `FORCE_COLOR`
> TTY detection.
- Colors only the status column while preserving plain ASCII layout and
summary output.
- Wires status rendering to the color gate in `_handle_status()`.
- Removes legacy `colorama.init()` from `update_checker.py`; package
init already enables Windows ANSI support.
- Adds unit tests for color gating and colored status rendering.
- No new dependencies or configuration changes.

### ⚙️ 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`: 1332 passed, 4 skipped).
- [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**
* Status output can now be shown with optional terminal colors for
improved readability.
* Color display automatically follows your terminal and environment
settings.

* **Bug Fixes**
* Status tables keep proper alignment even when colored text is enabled.
  * Unknown statuses remain uncolored, avoiding inconsistent display.

* **Tests**
* Added coverage for color handling and status rendering to improve
reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-26 13:48:53 +02:00
Jens
50a4b570cf feat: add ad status command (#1177)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Adds a CLI status overview inspired by useful lifecycle features from
kleinanzeigen-bot-ui, while keeping this project CLI-only.
- The new command helps users see local ad state at a glance without
replacing the existing verify/APR preflight flow.

## 📋 Changes Summary

- Add `kleinanzeigen-bot status` with an ASCII table and summary for
local ad states: disabled, draft, changed, due, and published-local.
- Add shared pure helpers for content-change and republication-due
checks.
- Add a small neutral `load_ad_configs()` loader reused by `load_ads()`
and `status` without broad loader redesign.
- Add German translations and focused unit/guardrail tests.
- No schema/config model 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)
- [x]  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.

Validation:
- `pdm run format` passed
- `pdm run lint` passed
- `pdm run test`: 1315 passed, 4 skipped; coverage 93.18%


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added a new `status` command to view the current state of configured
ads.
* Introduced a status summary that shows whether ads are disabled,
drafts, changed, due, or published locally.
* Added cleaner handling for ad loading and republication checks,
improving consistency in displayed results.
* **Bug Fixes**
* Improved change detection for ads, including better handling when
stored data is missing or empty.
  * Enhanced due-date checks so timing-based status is more reliable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-26 12:23:26 +02:00
Jens
d5d596d481 fix: target visible Auth0 submit button and broaden captcha detection (#1120) (#1176)
## ℹ️ Description

Fixes #1120 — Auth0 login fails after email submit because the bot
clicks a hidden submit button and cannot detect non-reCAPTCHA captcha
providers.

**Root causes:**
1. **Hidden submit button** — Auth0 renders two `button[type='submit']`
elements. The hidden one (`class=ulp-hidden-form-submit-button`,
`aria-hidden=true`) appears first in DOM. `querySelector()` was matching
it instead of the visible primary button.
2. **Captcha detection too narrow** — Only matched reCAPTCHA v2 iframes.
Kleinanzeigen.de uses Cloudflare Turnstile via Auth0 v2
(`data-captcha-provider='auth0_v2'`), which renders inline without an
iframe.

**Evidence:** @jochenberger provided HTML from the identifier page
confirming both issues. User CAN manually click 'Weiter' and login
succeeds.

## 📋 Changes Summary

- Add `_click_auth0_submit()` helper using
`[data-action-button-primary='true']` to target the visible button
- Broaden captcha detection: iframe selector covers 6 providers,
container selector uses `[data-captcha-provider]` + substring class
matching
- Simplify `handle_identifier_captcha_state()` with Turnstile token wait
via JS property check
- Use `_click_auth0_submit()` for both identifier and password submits
- Add Auth0 provider provenance comments to selectors

### ⚙️ 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 captcha/challenge detection to support both iframe-based
providers and Auth0 container-based challenges.
- Updated the Auth0 login flow to click the correct visible Auth0
primary submit button, avoiding hidden controls for identifier and
password steps.
- Centralized captcha detection timeout to make challenge handling more
consistent.

- **Tests**
- Expanded and tightened unit tests for the Auth0 identifier-step
captcha/submit behavior, including selector expectations and
control-flow scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-26 07:50:00 +02:00
kleinanzeigen-bot-tu[bot]
69e5b0cb9b chore: Update Python dependencies (#1175)
✔ Update click 8.4.1 -> 8.4.2 successful
  ✔ Update ruff 0.15.18 -> 0.15.19 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-26 07:49:42 +02:00
kleinanzeigen-bot-tu[bot]
32b7881a72 chore: ✔ Update coverage 7.14.2 -> 7.14.3 (#1173)
✔ Update coverage 7.14.2 -> 7.14.3 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-24 10:38:27 +02:00
Jens
8e70d0411d refactor: decompose WebScrapingMixin (static helpers, diagnostics, exception annotations) (#1174)
## ℹ️ Description

Decompose `WebScrapingMixin` — incremental internal refactors to reduce
class size and improve separation of concerns.

## 📋 Changes Summary

### Static method extraction
- Extract 5 `@staticmethod` members from `WebScrapingMixin` to
module-level private functions in `web_scraping_mixin.py`
- Update internal call sites and test call sites (no compatibility
aliases)

### Browser diagnostics extraction
- Create `src/kleinanzeigen_bot/utils/browser_diagnostics.py` with
module-level diagnostic functions
- `WebScrapingMixin.diagnose_browser_issues()` → thin delegator
(resolves `self` attrs, calls extracted logic)
- Replace `self`-coupled logic with explicit parameter dependencies
- Migrate translations to new module section in `translations.de.yaml`

### Exception annotations
- Add `# noqa: BLE001` + justification comments to 4 bare `except
Exception:` blocks (no behavior changes)

### ⚙️ Type of Change
- [x] 🔧 Refactor (internal code improvements, no behavior changes)

##  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`) — 1287 passed, 4 skipped
- [x] I have formatted the code (`pdm run format`)
- [x] I have verified that linting passes (`pdm run lint`) — ruff, mypy,
pyright clean
- [x] I have updated documentation where necessary.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added enhanced browser troubleshooting with remote-debugging
connectivity checks, running-process inspection, and Chrome/Edge
compatibility validation including recommended configuration updates.
* **Refactor**
* Reorganized browser/session diagnostics and remote-debugging argument
handling into dedicated utilities; introduced a shared browser runtime
configuration container.
* **Chores**
* Suppressed linter warnings for intentionally broad exception handling.
* **Tests**
* Updated unit and integration tests to match the new diagnostics flow
and remote-debugging probing behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-24 10:36:42 +02:00
Jens
b2dce90ef1 refactor: remove dead wrapper methods from KleinanzeigenBot (#1172)
## ℹ️ Description

Remove four private wrapper methods on `KleinanzeigenBot` in `app.py`
that wrap public module-level functions but have zero production call
sites. This is a cleanup-only change with no behavioral impact.

## 📋 Changes Summary

- **Remove** `_has_logged_in_marker` — delegates to
`login_flow.has_logged_in_marker`
- **Remove** `_check_publishing_result` — delegates to
`publishing_workflow.check_publishing_result`
- **Remove** `_delete_old_ad_if_needed` — delegates to
`publishing_workflow.delete_old_ad_if_needed`
- **Remove** `_capture_login_detection_diagnostics_if_enabled` —
delegates to `login_flow.capture_login_detection_diagnostics_if_enabled`
- **Remove** unused `Literal` import
- **Retarget** 4 helper-detail tests that called the deleted wrapper
directly to the real
`login_flow.capture_login_detection_diagnostics_if_enabled` function

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

* **Refactor**
* Reorganized login detection diagnostics functionality for improved
accessibility
* Simplified login status verification logic within the authentication
system

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 21:37:17 +02:00
Jens
dedf4cb4f0 refactor: extract template name renderer from AdExtractor (#1171)
## ℹ️ Description

Extract the priority-based template rendering algorithm from
`_render_download_name_with_budget` into a module-level pure function
`_render_name_with_budget`. The method becomes a thin wrapper that
delegates rendering and handles truncation warnings.

## 📋 Changes Summary

- Added `_render_name_with_budget(template, ad_id, title, max_length) ->
tuple[str, bool, bool]` as a module-level pure function with no
AdExtractor dependency
- Rewrote `_render_download_name_with_budget` as a thin wrapper that
calls the pure function and handles logging
- Removed `_reserved_for_pending_placeholders` static method (logic
inlined in the pure function)

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Improved download name handling with enhanced truncation logic for
improved filename generation.
* Added warnings when download names are automatically shortened due to
length constraints.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 20:57:25 +02:00
dependabot[bot]
e15c57f131 ci(deps): bump actions/checkout from 6.0.3 to 7.0.0 in the all-actions group (#1170)
Bumps the all-actions group with 1 update:
[actions/checkout](https://github.com/actions/checkout).

Updates `actions/checkout` from 6.0.3 to 7.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>block checking out fork pr for pull_request_target and workflow_run
by <a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
<li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li>
<li>Bump flatted from 3.3.1 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li>
<li>Bump js-yaml from 4.1.0 to 4.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li>
<li>Bump <code>@​actions/core</code> and
<code>@​actions/tool-cache</code> and Remove uuid by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li>
<li>upgrade module to esm and update dependencies by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li>
<li>Bump the minor-npm-dependencies group across 1 directory with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li>
<li>getting ready for checkout v7 release by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2464">actions/checkout#2464</a></li>
<li>update error wording by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2467">actions/checkout#2467</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.0">https://github.com/actions/checkout/compare/v6.0.3...v7.0.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9c091bb21b"><code>9c091bb</code></a>
update error wording (<a
href="https://redirect.github.com/actions/checkout/issues/2467">#2467</a>)</li>
<li><a
href="1044a6dea9"><code>1044a6d</code></a>
getting ready for checkout v7 release (<a
href="https://redirect.github.com/actions/checkout/issues/2464">#2464</a>)</li>
<li><a
href="f0282184c7"><code>f028218</code></a>
Bump the minor-npm-dependencies group across 1 directory with 3 updates
(<a
href="https://redirect.github.com/actions/checkout/issues/2462">#2462</a>)</li>
<li><a
href="d914b262ff"><code>d914b26</code></a>
upgrade module to esm and update dependencies (<a
href="https://redirect.github.com/actions/checkout/issues/2463">#2463</a>)</li>
<li><a
href="537c7ef99c"><code>537c7ef</code></a>
Bump <code>@​actions/core</code> and <code>@​actions/tool-cache</code>
and Remove uuid (<a
href="https://redirect.github.com/actions/checkout/issues/2459">#2459</a>)</li>
<li><a
href="130a169078"><code>130a169</code></a>
Bump js-yaml from 4.1.0 to 4.2.0 (<a
href="https://redirect.github.com/actions/checkout/issues/2461">#2461</a>)</li>
<li><a
href="7d09575332"><code>7d09575</code></a>
Bump flatted from 3.3.1 to 3.4.2 (<a
href="https://redirect.github.com/actions/checkout/issues/2460">#2460</a>)</li>
<li><a
href="0f9f3aa320"><code>0f9f3aa</code></a>
Bump actions/publish-immutable-action (<a
href="https://redirect.github.com/actions/checkout/issues/2458">#2458</a>)</li>
<li><a
href="f9e715a95f"><code>f9e715a</code></a>
block checking out fork pr for pull_request_target and workflow_run (<a
href="https://redirect.github.com/actions/checkout/issues/2454">#2454</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v6.0.3...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=6.0.3&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 16:19:09 +02:00
Jens
1f142f8339 refactor: extract selector and filter helpers from load_ads (#1169)
## ℹ️ Description

Extract three private helpers from `load_ads()` to remove the last
remaining `# noqa: PLR0915` annotation in main source. `load_ads` goes
from ~100 statements to ~35 — a clean orchestration function.

## 📋 Changes Summary

- **`_parse_ad_selector`**: parse `ads_selector` string into numeric IDs
list or frozenset of tokens
- **`_should_include_ad`**: token-based ad filtering
("changed"/"new"/"due"/"all") — preserves exact ordering, side effects,
and "changed"/price-reduction-for-update logic
- **`_prepare_selected_ad_entry`**: description validation, category
resolution, image resolution — called only after filtering to avoid
validating skipped ads
- Translation keys moved to match new caller function names
(`_should_include_ad:`, `_prepare_selected_ad_entry:`)
- Added regression test: inactive ad with unresolvable images is skipped
without error

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

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 ad loading process with improved selector parsing and
filtering logic for better code maintainability.
* Optimized validation workflow: inactive and non-selected ads now skip
description and image validation, improving overall efficiency.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 16:07:04 +02:00
Jens
388d0fb3c8 refactor: separate download ad persistence concerns (#1168)
## ℹ️ Description

Separate downloaded-ad persistence concerns from `download_ad()` in
`extract.py`. The original method mixed browser extraction,
local-settings preservation, and a filesystem transaction — three
independently meaningful and operationally sensitive concerns.

## 📋 Changes Summary

- **Extracted `_preserve_local_settings_from_existing_ad()`** —
preserves local-only settings (repost_count, republication_interval,
auto_price_reduction, price_reduction_count) from an existing ad YAML
into the new config. No-op unless `preserve_local_settings` is enabled.
- **Extracted `_commit_staged_download()`** — owns the full filesystem
transaction: YAML save, backup collision check, rename
final→backup→staging→final, backup cleanup, and rollback on failure.
- **Simplified `download_ad()`** — now a clean 3-step orchestrator:
extract → preserve → commit.
- **Restructured translation keys** in `translations.de.yaml` to follow
the new caller function names.

No behavior changes to preservation, rollback, YAML handling, or
exception propagation.

### ⚙️ 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**
* Enhanced ad download process with improved backup and rollback
mechanisms for better reliability
* Refined handling of local settings preservation during re-downloads to
maintain data integrity

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 15:31:13 +02:00
Jens
eeeae6ea5e refactor: extract shipping helpers from set_shipping (#1167)
## ℹ️ Description

Refactor `set_shipping` in `publishing_form.py` by extracting four
distinct concerns into focused private helpers. Simplifies a
~55-statement function into a ~20-statement orchestrator with a flat
if-return chain.

## 📋 Changes Summary

- Extract `_select_shipping_combobox_if_present` — PRO/commercial
combobox handling
- Extract `_set_pickup_shipping` — PICKUP radio + fieldset fallback
- Extract `_set_configured_shipping_options` — shipping options dialog +
MODIFY nav
- Extract `_enable_platform_default_shipping` — enable shipping toggle
- Keep legacy `shipping_costs` guard inline in `set_shipping` (per
review)
- Re-key translation entries under new caller-function names (duplicate
"Failed to set shipping..." under both combobox and pickup helpers)
- `set_shipping` slimmed from ~55 → ~20 ruff-counted statements

### ⚙️ 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
* **Shipping configuration**: Refactored the shipping configuration
logic to improve internal code structure and maintainability, enabling
more reliable handling of shipping options across different scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 13:16:37 +02:00
Jens
780743aee2 refactor: separate download_ads workflow modes (#1166)
## ℹ️ Description

Extract four private async helpers from `download_ads()` to separate
per-mode workflow logic.

- Motivation: Reduce function complexity, enable tighter pylint
thresholds

## 📋 Changes Summary

- Extracted `_fetch_published_ads_by_id` — fetch and build published ads
lookup dict
- Extracted `_download_all_ads` — download all ads from overview page
- Extracted `_download_new_ads` — download only unsaved ads (preserving
URL dedup behavior)
- Extracted `_download_ads_by_ids` — download specific ads by numeric ID
(preserving distinct warning semantics)
- Slimmed `download_ads()` to ~48-line orchestrator (was ~124 lines)
- Restructured `translations.de.yaml` — messages moved to per-function
sections
- Ratcheted pylint thresholds: max-statements 90→76, max-branches 35→31

### ⚙️ Type of Change
- [ ] 🐞 Bug fix
- [ ]  New feature
- [ ] 💥 Breaking change

Internal refactor, no user-visible behavior 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`): 1286 passed, 4 skipped
- [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

* **Chores**
* Strengthened code quality standards and refactored internal ad
downloading logic for improved maintainability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 11:28:23 +02:00
Jens
eaa646874d refactor: replace get_message_template match with dict lookup (#1165)
## ℹ️ Description

Replace the ~115-arm match/case in `__get_message_template` with a
module-level `_MESSAGE_TEMPLATES` dict of raw English strings plus a
3-line lazy `_(template)` lookup function.

- **Motivation**: Eliminate 5 complexity `noqa` annotations (C901,
PLR0911, PLR0912, PLR0915, E701) by removing the real architectural
complexity — a pure flat error-code → message mapping that has zero
branching or logic.
- **Approach**: A `dict[str, str]` of raw English strings (no `_()`
calls at import time) with lazy translation inside
`__get_message_template`. `"custom_error"` intentionally omitted —
handled by `.get()` default.
- **Translation**: Caller function name unchanged → translation keys
under `__get_message_template` preserved. AST-based translation test
extractor updated to recognize `_MESSAGE_TEMPLATES` dict values.

## 📋 Changes Summary

- `src/kleinanzeigen_bot/utils/pydantics.py`: Replaced ~115 match arms
with `_MESSAGE_TEMPLATES` dict + 3-line function; removed all 5 noqa
annotations
- `tests/unit/test_translations.py`: Added AST extraction for
`_MESSAGE_TEMPLATES` dict values to maintain translation coverage checks

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Improved error message handling system to support better
internationalization and translation workflows

* **Tests**
* Updated test suite to extract and verify translatable message strings

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 07:12:23 +02:00
Jens
32c6d3985f refactor: split published ads pagination (#1164)
## ℹ️ Description

Extract content-decoding and paging-navigation logic from
`fetch_published_ads` into focused module-level helpers, reducing
function complexity while preserving all behavior.

## 📋 Changes Summary

- **`published_ads.py`**: Extracted `_parse_published_ads_page()`
(content decode, JSON parse, payload validation, ad filtering) and
`_determine_next_page()` (paging metadata resolution,
last-page/empty-ads guards). Main `fetch_published_ads` is now a clean
orchestration loop: request → response check → parse → extend →
paginate.
- **`translations.de.yaml`**: Split the single `fetch_published_ads:`
translation section into three sections (`fetch_published_ads:`,
`_parse_published_ads_page:`, `_determine_next_page:`) matching the new
caller function names. Added missing translation for "No paging dict
found on page %s".
- **`pyproject.toml`**: Lowered `max-statements` from 115 to 90.
- **`pydantics.py`**: Added `PLR0915` noqa for `__get_message_template`
(already an approved exception for the generated pydantic error-code
mapping).

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Improved published-ads fetching by separating response decoding and
pagination handling into dedicated helpers, while preserving existing
behavior.
* Reworked strict-mode validation and stopping conditions for clearer
control flow and more consistent error handling.

* **Chores**
  * Updated linting limits to enforce stricter code quality.
  * Added targeted lint suppression for an overly complex section.

* **Tests**
* Expanded unit test coverage for published-ads content decoding and
strict-mode failure cases across multiple malformed/edge responses.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-21 22:39:36 +02:00
Alex Strutsysnkyi
c6843a49c0 fix: avoid TypeError abort when web_request gets a non-dict response (#1162)
## ℹ️ Description

When publishing a batch of ads, a single transient page-load failure
could crash the **entire** run with an unhandled `TypeError`.

During the pre-publish delete step, `delete_flow.delete_ad` calls
`web_request`, which runs a `fetch(...)` via `web_execute`. When the
page context is torn down mid-navigation (the same condition that
surfaces as *"Page did not finish loading within 30.0 seconds"*),
`web_execute` returns a CDP `ExceptionDetails` object (or `None`)
instead of the expected response dict. `web_request` then does
`response["statusCode"]`, raising:

```
TypeError: [ExceptionDetails] object is not subscriptable
  File ".../utils/web_scraping_mixin.py", line 1537, in web_request
    response["statusCode"] in valid_response_codes,
```

This `TypeError` is **not** caught by the publish retry loop (which
handles `TimeoutError` / `ProtocolException`), so it propagates all the
way up and aborts the whole batch — every remaining ad goes unpublished.

Observed live while publishing ~25 ads: 9 published successfully, two
hit transient load timeouts, and the next `delete_ad` request crashed
the process.

- Link to the related issue(s): Issue #

## 📋 Changes Summary

- `web_request`: guard the response — if it is not a `dict` containing
`statusCode`, raise a `ProtocolException` (already imported) instead of
blindly subscripting it.
- `ProtocolException` is already handled by the publish retry/skip
logic, so a single transient failure now retries and then skips that one
ad, letting the rest of the batch continue.
- Add a parametrized regression test in `test_web_scraping_mixin.py`
covering `None` / non-dict / missing-`statusCode` responses.

### ⚙️ 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 the affected tests pass
(`pytest tests/unit/test_web_scraping_mixin.py -k web_request` → 7
passed).
- [ ] I have formatted the code (`pdm run format`).
- [ ] I have verified that linting passes (`pdm run lint`).
- [ ] I have updated documentation where necessary (n/a).

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**
* Enhanced validation for network operation responses with improved
error messaging for unexpected situations, preventing hidden failures
and providing clearer diagnostics when issues occur.

* **Tests**
* Extended test coverage to comprehensively validate error handling
across various edge cases and unexpected response scenarios in network
operations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-21 20:16:52 +02:00
kleinanzeigen-bot-tu[bot]
0c75eea071 chore: Update Python dependencies (#1163)
✔ Update wrapt 2.2.1 -> 2.2.2 successful
  ✔ Update coverage 7.14.1 -> 7.14.2 successful

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-21 19:37:22 +02:00
Jens
b5e2769f2d refactor: extract special attribute helpers from publishing form (#1161)
## ℹ️ Description

Extract three module-level helpers from `set_special_attributes()` in
`publishing_form.py` to reduce local variable count and improve
readability. `set_special_attributes` had 27 locals — after extraction
it has 10.

- Behavior-preserving: no change to exception propagation, logging, or
control flow.
- `condition_s` probe stays in main to avoid translation-key churn.

## 📋 Changes Summary

- Extract `_build_special_attribute_xpath()` — Pure XPath construction
(fix comment: five → six patterns)
- Extract `_resolve_special_attribute_element()` — Wraps `web_find_all`
+ candidate pick, propagates exceptions uncaught
- Extract `_set_special_attribute_input()` — 6-branch input-type
dispatch; hidden-input returns without logging, caller logs once
- Rewire `set_special_attributes` to call the three helpers
- Ratchet `pyproject.toml`: PLR0914 max-locals 27 → 20
- Update `translations.de.yaml`: move 4 debug messages + add `Failed to
set attribute` under `_set_special_attribute_input`

### ⚙️ 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 (non-breaking restructuring of existing code)

##  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`). → 1268 passed, 4 skipped
- [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. → Translation file
updated


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **Chores**
* Tightened linting rules by lowering the allowed maximum number of
local variables.

* **Refactor**
* Reworked special-attribute DOM handling to use clearer selection and
value-setting paths for different field types, including improved
fallback behavior.

* **Tests**
* Added async unit test coverage for `set_special_attributes`, including
input fallback behavior and error cases for unsupported checkbox values
and missing hidden input metadata.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-21 19:36:56 +02:00
Jens
d542f1ea92 feat: use configured --remote-debugging-host for browser diagnostics probes (#1160)
## ℹ️ Description

`diagnose_browser_issues()` previously hardcoded `127.0.0.1` for
port-open and `/json/version` API probes. When Chrome's remote debugging
is exposed on a different host (Docker, LAN, CI), the diagnostics miss
the running browser entirely.

This PR makes diagnostics host-aware by parsing
`--remote-debugging-host` from `browser_config.arguments` and using the
configured host instead of the hardcoded `127.0.0.1`. All diagnostics
probes (port, API, Chrome version) now respect the configured host.

## 📋 Changes Summary

- Added `_diagnostic_remote_debugging_endpoint()` — private diagnostics
parser with first-wins semantics for both host and port, defaults to
`127.0.0.1:0`
- Added `_format_url_host()` — IPv6-safe URL bracketing helper
- Threaded configured host into `net.is_port_open()`,
`_remote_debugging_api_browser()`, and
`_diagnose_chrome_version_issues()`
- Emit `LOG.warning` before probing a non-loopback configured host
(security/documentation guard)
- Updated German translations for changed log message strings
- Added tests: configured host `10.0.0.5` and `192.168.1.100`,
host-after-port ordering, IPv6 URL formatting, Chrome-version host
propagation
- Default behavior (no `--remote-debugging-host` argument) unchanged —
probes remain `127.0.0.1`

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

* **Bug Fixes**
* Improved remote browser debugging diagnostics to work with non-local
hosts, including correct IPv6-safe URL formatting.
* Added host-aware reachability checks and clearer warnings when the
configured remote host may not be loopback.
* Enhanced diagnostic messaging to report the configured host and port
during remote debugging checks.

* **Tests**
* Expanded unit test coverage for configured remote-debugging hosts
(including IPv6) and updated expectations for host-specific diagnostic
outputs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-21 09:26:52 +02:00
Jens
d384f172b8 fix: remove individual shipping publishing (#1159)
## ℹ️ Description

- Link to the related issue(s): Issue #1157
- Kleinanzeigen no longer offers individual/custom shipping. This
updates publishing, validation, docs, schemas, translations, and tests
so existing `shipping_costs` configs are handled gracefully instead of
failing against removed DOM controls.

## 📋 Changes Summary

- Keep `shipping_costs` for legacy configs/downloaded ads, but mark it
deprecated in schema/docs and ignore it during publishing.
- Remove publishing interaction with removed individual-shipping DOM
controls.
- Require predefined non-empty `shipping_options` for `sell_directly`.
- Update docs, generated schemas/config artifacts, German translations,
and unit tests.
- Verified live DOM for `sell_directly: true` + `shipping_type:
SHIPPING` + predefined `shipping_options` via local ignored script; no
ad submission performed.

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

* **Documentation**
* Updated shipping guides to deprecate custom individual shipping costs
and make publishing depend on per-ad predefined `shipping_options`
(DHL/Hermes; selectable options must come from a single size group).
* Added migration guidance replacing `shipping_costs` with the correct
`shipping_options`.
* Clarified “Sell directly” requires `shipping_type: SHIPPING`,
non-empty `shipping_options`, and `FIXED`/`NEGOTIABLE` pricing.

* **Bug Fixes**
* Publishing is blocked when `shipping_costs` is provided without
`shipping_options`.
* Removed unsupported individual-shipping handling and tightened “Sell
directly” eligibility rules.

* **Tests**
* Expanded unit coverage for deprecation behavior, content handling, and
direct-buy validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-21 08:11:02 +02:00
Jens
5ab4015251 refactor: simplify browser diagnostics (#1158)
## ℹ️ Description

- Link to the related issue(s): Issue #
- Refactor browser diagnostics to reduce the complexity of the
diagnostics orchestration while preserving the generated diagnostics
report and browser workflow behavior.

## 📋 Changes Summary

- Extract factual browser diagnostic checks into focused helpers for
binary detection, remote debugging port parsing, remote API probing,
target browser name detection, and process discovery.
- Keep translated diagnostics logging as direct literal log calls in
`diagnose_browser_issues`.
- Add regression coverage for remote debugging host handling, invalid
ports, first-port precedence, and port `0` pass-through behavior.
- 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)
- [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

* **Refactor**
* Improved browser diagnostics by breaking down remote debugging checks
into clearer steps, enhancing resilience when probing the browser and
inspecting running processes, and refining success vs failure logging.

* **Tests**
* Expanded unit coverage to ensure remote debugging probing always
targets `http://127.0.0.1:<port>`, validates `--remote-debugging-port`
parsing (including invalid and multi-argument cases), and skips remote
debugging when the port is `0` while continuing Chrome version
diagnostics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-20 22:22:21 +02:00
Jens
0b4b9eb397 refactor: split browser session setup (#1156)
## ℹ️ Description

- Link to the related issue(s): N/A
- Split browser session setup into smaller, behavior-preserving helpers
so browser startup orchestration is easier to review and maintain.

## 📋 Changes Summary

- Extract remote debugging connection handling from browser session
creation.
- Extract launch argument, user-data-dir, Nodriver config, profile
preparation, and extension setup helpers.
- Add matching German translation entries for log messages moved into
helper functions.
- Leave lint thresholds unchanged because the diagnostics follow-up
remains separate.

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

## Summary by CodeRabbit

* **Refactor**
* Improved browser session setup by separating remote-debugging
connections from fresh browser startup.
* Hardened launch argument construction and user data directory
resolution for more consistent configuration.
* Improved browser startup failure cleanup to ensure resources are
released reliably.
* Kept troubleshooting output behavior, including better guidance for
debugging scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-20 14:54:15 +02:00
Jens
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 -->
2026-06-20 12:33:06 +02:00