263 Commits

Author SHA1 Message Date
orangecoding
ec47137b89 upgrading dependencies 2026-05-21 21:40:35 +02:00
Stephan
acab23207e fix: kleinanzige listing might have a different structure when it was with no image created (#308) 2026-05-16 14:16:31 +02:00
orangecoding
2896d531e4 upgrading pois 2026-05-13 08:14:57 +02:00
orangecoding
0cbfa25062 upgrading pois 2026-05-12 19:28:58 +02:00
orangecoding
0ce93acaf6 more demo fixes 2026-05-12 13:12:26 +02:00
orangecoding
cabef973a2 forbid backuo/restore in demo mode 2026-05-12 12:42:25 +02:00
orangecoding
8b012ef2f1 upgrading dependencies / new pois 2026-05-11 09:18:32 +02:00
Christian Kellner
ac02817d4e Switch browser engine from puppeteer-extra/stealth to CloakBrowser (#307)
* Switch browser engine from puppeteer-extra/stealth to CloakBrowser

- Replace puppeteer, puppeteer-extra, puppeteer-extra-plugin-stealth with
  cloakbrowser + puppeteer-core; CloakBrowser applies 49 source-level C++
  fingerprint patches that cannot be detected at the JS layer.
- Enable humanize:true in launchBrowser() for Bézier mouse curves, natural
  keyboard timing, and realistic scroll physics.
- Remove manual userDataDir management and ARM64 executablePath override;
  CloakBrowser ships its own binary for x86_64 and arm64.
- Proxy is now passed via CloakBrowser's native proxy option instead of
  --proxy-server Chrome flag.
- Dockerfile: add fonts-noto-color-emoji + fonts-freefont-ttf so canvas
  fingerprint hashes match real browsers (required for Kasada/Akamai);
  replace npx puppeteer browsers install with node ensureBinary() call;
  remove TARGETARCH ARG and ARM64 system-Chromium branch.
- Update test mock to reflect simplified browser object (no __fredy_* fields).

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Add --ignore-certificate-errors for CloakBrowser's custom Chromium

CloakBrowser ships its own Chromium binary with an independent CA bundle.
This flag prevents ERR_CERT_AUTHORITY_INVALID failures in environments with
SSL-inspecting proxies or non-standard root CAs (Docker CI, corporate networks).

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Harden CloakBrowser integration and fix kleinanzeigen detail test

- Remove all CDP overrides (applyBotPreventionToPage, applyLanguagePersistence,
  applyPostNavigationHumanSignals) that created detectable inconsistencies on top
  of CloakBrowser's C++ patches; pass locale to CloakBrowser launch instead
- Drop --lang arg (replaced by CloakBrowser locale flag)
- Extend immowelt puppeteerTimeout to 90 s to accommodate React SPA rendering
  latency under CloakBrowser's humanise delays
- Fix kleinanzeigen detail test: serve the offline fixture for the search URL
  so only individual detail pages are fetched live, avoiding rate limiting from
  a second fresh session hitting the same search endpoint

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Fix immowelt bot detection with two-phase navigation and fixture-backed detail test

Immowelt's CDN challenges cold browser sessions before React can render the
listing grid, causing the old waitForSelector approach to silently timeout.

- Add preNavigateUrl option to puppeteerExtractor: visits a warm-up page
  first so the site sees an established session before the search URL
- Add waitForNetworkIdle option: a second idle-wait phase after domcontentloaded
  that catches React's listing API round-trip (which fires long after the
  initial HTML is parsed); errors are swallowed so partial DOM is still used
- Switch immowelt config to waitForSelector=null + networkidle warm-up so
  page.content() is returned after the SPA has loaded its data
- Set immowelt preNavigateUrl to the homepage to warm the session
- In the detail enrichment test, spy on puppeteerExtractor to serve the
  offline fixture for the search URL; only individual listing detail pages
  are fetched live (they are far less aggressively protected)

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Ensure CloakBrowser binary is present before any live test runs

Add a Vitest globalSetup that calls ensureBinary() once in the main process
before workers start. Without this, running yarn test on a fresh checkout
(or after the binary cache is cleared) immediately fails every browser-based
test with "Failed to launch the browser process" before any useful output
appears. The setup is a no-op in offline mode and when the binary is already
cached.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Ensure CloakBrowser binary at startup for non-Docker installs

Direct runs (yarn start:backend) on a fresh checkout have no binary and
only crash when the first scraping job fires. Calling ensureBinary() at
startup downloads it on first run and is instant when already cached.
In Docker it stays a no-op since the binary is pre-baked during docker build.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Fix --no-zygote comment: ICU crash was corrupted .4 binary, not fd issue

The "Invalid file descriptor to ICU data received" crash seen in Sparkasse
tests was caused by a partially-extracted CloakBrowser .4 binary that
contained only the chrome executable but was missing icudtl.dat and other
resource files. The ensureBinary() function returned this incomplete
installation because latest_version_linux-x64 pointed to .4.

The --no-zygote flag is kept as a safeguard for container environments
with limited kernel namespaces, but the comment now accurately describes
its purpose rather than attributing it to a non-existent fd inheritance issue.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Add ensureValidBinary() to detect and auto-heal corrupt CloakBrowser installs

CloakBrowser's ensureBinary() only checks that the chrome executable exists,
not that required resource files (icudtl.dat, resources.pak) are present.
A partial extraction — e.g. an interrupted update — can leave a directory
that passes ensureBinary()'s check but causes Chrome to crash immediately
with "Invalid file descriptor to ICU data received".

ensureValidBinary() wraps ensureBinary() with a completeness check:
- If the required resource files are missing it removes the corrupt directory
  and all latest_version* markers, then calls ensureBinary() again so it
  falls back to (or re-downloads) a complete build.
- It pins the validated path via CLOAKBROWSER_BINARY_PATH so CloakBrowser's
  own internal ensureBinary() call inside launch() always uses the same,
  verified binary.

Used in index.js (app startup) and test/globalSetup.js (before live tests).

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Fix sparkasse detail test: serve search URL from fixture to avoid rate-limiting

The second sparkasse test launched a fresh browser against the live search
endpoint right after the first test already did, leaving the IP in a suspicious
state that caused bot detection or rate-limiting to return empty results.
When getListings() returns nothing, execute() resolves to undefined and
expect(listings).toBeInstanceOf(Array) fails.

Apply the same hybrid fixture approach used by kleinanzeigen and immowelt:
intercept puppeteerExtractor calls whose pathname matches the search URL and
return the offline fixture, while letting individual detail page requests go
live (they are less aggressively rate-limited than the search endpoint).

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Fix sparkasse detail test: shared browser, direct fetchDetails call

Remove the fixture-backed spy — live tests must hit the real server.

Root problem: two cold browser sessions hitting sparkasse in quick succession
triggered bot detection, causing the second search request to return empty
results and execute() to resolve undefined.

Fix:
- One browser launched in beforeAll and reused across both tests, so both
  the search and detail requests come from the same warm session.
- The detail test calls provider.config.fetchDetails() directly on the
  listings returned by the first test instead of re-running the full pipeline.
  This avoids a redundant second scrape of the search page while still
  exercising the live detail endpoint.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Eliminate fixture spies and double live requests in all provider detail tests

All five provider tests with a 'with provider_details enabled' describe block
were either (a) intercepting the search URL with an offline fixture to avoid
hitting the live server twice, or (b) re-running the full execute() pipeline
with a fresh browser, which triggered rate-limiting / bot detection on the
second cold request.

Pattern applied to all five:
- immowelt, kleinanzeigen, wgGesucht, immobilienDe: launch one browser in
  beforeAll/afterAll, pass it to the first test's Fredy constructor, and call
  provider.config.fetchDetails() directly in the second test using the listings
  and browser already in hand. One warm session, two live endpoints tested.
- immoscout: API-based (no browser), so no browser sharing needed. Second test
  calls provider.config.fetchDetails() directly on liveListings[0] from the
  first test instead of re-querying the search API.

Removed: all readFixture spies, getKnownListingHashesForJobAndProvider mocks,
and the puppeteerExtractorMod imports that were only needed for the spy.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

* Fix ensureValidBinary for macOS: platform-aware completeness check

On macOS the CloakBrowser binary lives at:
  ~/.cloakbrowser/chromium-X.Y.Z/Chromium.app/Contents/MacOS/Chromium

path.dirname() gave Contents/MacOS/ — but icudtl.dat and resources.pak
are inside Contents/Frameworks/…, not next to the binary. So the old
code incorrectly flagged every macOS installation as corrupt, deleted only
the MacOS/ subdirectory (not the full versioned dir), then failed again.

Fixes:
- isBinaryComplete: on macOS check for Info.plist and Frameworks/ inside
  Chromium.app/Contents/ instead of looking for Linux resource files next
  to the binary. On Linux/Windows the existing check is unchanged.
- getVersionedDir: resolves the full chromium-X.Y.Z/ directory regardless
  of platform (4 levels up on macOS, 1 on Linux/Windows) so
  removeCorruptInstallation always deletes the entire versioned tree.
- missingDescription: reports the correct missing items per platform.

https://claude.ai/code/session_01WXzA3orbwE2hdk723c6MgH

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-10 15:42:31 +02:00
orangecoding
921057252d adding immoscout shape search 2026-05-07 19:11:47 +02:00
orangecoding
703c602527 table overview for jobs 2026-05-07 15:59:55 +02:00
datenwurm
f60c5859f9 feat: Add grid/table view toggle to listings overview (#305)
* feat: Add delete button to listing detail view

* feat: Add grid/table view toggle to listings overview

---------

Co-authored-by: datenwurm <git@datenwurm.net>
2026-05-07 12:12:49 +02:00
orangecoding
96582ecff4 gmx example 2026-05-02 20:07:03 +02:00
orangecoding
3de82dfa41 fixing error message when passwords do not match / fixing placeholder image 2026-05-02 20:00:11 +02:00
orangecoding
3d10dc6042 moving from restana to fastify 2026-04-27 16:56:04 +02:00
orangecoding
8a7b14c079 fixing toasts not showing on certain pages / adding statement about ai 🤖 2026-04-27 15:58:41 +02:00
orangecoding
c78472bd19 adding 'open in fredy' 2026-04-21 19:42:39 +02:00
orangecoding
8c5607e20b adding test fixtures so that we can run tests 'offline' 2026-04-21 13:37:00 +02:00
bytedream
cc0164b689 change average price to median price on the dashboard (#300)
* change average price to median price on the dashboard

* Use more efficient median calculation

Co-authored-by: Christian Kellner <weakmap@gmail.com>

* Fix applied suggestion artifacts

* Update sql query and js sort function

* Group sql statement by id

* Revert sort function change

---------

Co-authored-by: Christian Kellner <weakmap@gmail.com>
2026-04-20 10:13:11 +02:00
Adrian Bartnik
c384781137 Add toggle for plain text message to telegram notification adapter (#299) 2026-04-16 12:05:57 +02:00
orangecoding
e2d10d179e next release version 2026-04-12 09:21:08 +02:00
Stephan
10c94eea0a Feature/spec filter (#276)
* feat(): create map component, add area filtering to the job config

* feat(): filter listings by area filter

* chore(): cleanup

* feat(): solve feedback

* feat(): solve most providers

* feat(): solve maybe other providers

* feat(): add specFilter config, also add rooms to listing

* feat(): change tests

* feat(): fix kleinanzeigen parser

* feat(): add spec filter switch for listing overviiews

* feat(): add rooms and size to the overview and detail of a listing

* feat(): rem label

* feat(): add types, update providers, they now return specs as numbers

* feat(): add jsonconfig to enable type checks

* feat: add type for prividerConfig, add fieldNames per provider

* feat: fix tests, provider, add formatListing

* chore: remov duplicates

* feat(): fix tests

* feat: fix immoscout

* chore: geojson typing

* feat: solve requested changes
2026-04-12 09:17:23 +02:00
orangecoding
05f74f99ef adding tool to receive photo of listing 2026-04-09 11:51:42 +02:00
orangecoding
f3ad529107 fixing migration file 2026-04-07 20:22:16 +02:00
Christian Kellner
cdc0cbda2f Feature/kleinanzeigen new (#292)
* Feature/Kleinanzeigen addresses (#289)

* upgrade dependencies

* immoscout_details -> provider_details

* fetching details more generic

* removing claude action

* fixing sparkassen selector

* improvements

* fixing immobilienDE test

* upgrading dependencies

* settings for many provider

---------

Co-authored-by: Adrian Bach <65734063+realDayaa@users.noreply.github.com>
2026-04-07 19:53:40 +02:00
orangecoding
d7f46d6c68 security update 2026-03-31 13:33:01 +02:00
orangecoding
a1289acf15 fixing some docker issues 2026-03-22 09:41:20 +01:00
orangecoding
b531a7b77a fixing mcp issue, adding claude example 2026-03-20 13:45:42 +01:00
Adrian Bach
3523057221 feat: add smtp adapter (#279) 2026-03-20 11:37:28 +01:00
orangecoding
556c0aff35 fixing duplicate migration 2026-03-17 11:26:23 +01:00
Promises
6c08675fee Add new properties to real estate translation mappings (#275)
Added few more properties for buying a house
2026-03-11 14:49:21 +01:00
orangecoding
34c4de7267 fixing stdin for mcp 2026-03-10 09:27:04 +01:00
orangecoding
b64a118a18 moving mcp into lib to make it available in docker setup 2026-03-09 16:26:53 +01:00
orangecoding
be5c4af3cf adding an MCP Server 🎉 2026-03-09 15:35:29 +01:00
orangecoding
4596442f64 upgrading dependencies | mark listings as 'manually_removed' when filtered 2026-03-08 09:55:46 +01:00
Stephan
0bcfa1d4ad feat(): map area filter (#273)
* feat(): create map component, add area filtering to the job config

* feat(): filter listings by area filter

* chore(): cleanup

* feat(): solve feedback

* feat(): solve most providers

* feat(): solve maybe other providers
2026-03-08 09:44:18 +01:00
orangecoding
0cad05124a fixing immowelt provider 2026-03-08 09:29:40 +01:00
Noah Elijah Till
eb53b68d45 🕵️ More immoscout details (#258)
* 🕵️ More immoscout details

- Added more details to immoscout api - description is now populated with a lot of data from the expose using app API
- You can ignore certificates, if deploying locally and using the http notification adapter
- More details for the test call/example for easier testing + placeholder image + actual values + address (famous Erika Mustermans address see https://de.wikipedia.org/wiki/Mustermann)
- Grater timeout for geocode since the api is sometimes slow in germany
- uiElement, type boolean, now has a label as well

* 👀 Requested changes + some extra

Req:
- using logger
- using node-fetch

Extra:
- boolean input fields will trigger the validate check, because they are set undefined at first - setting them to false if they are undefined now
- added more data to the description (phone number and name of the agent)

*  Fixed import

* ️ Toggle immoscout detail fetching

* ️ Requested change
2026-03-08 09:08:40 +01:00
Tom Dohrmann
ba0732e1f6 add support for fulltext parameter for immoscout (#274) 2026-02-24 09:53:14 +01:00
orangecoding
aa67647bbb adding resend as net notification adapter 2026-02-20 17:08:38 +01:00
orangecoding
7a9d49899b improve reusing of puppeteer by adding a safeguard for broken chrome 2026-02-18 20:16:55 +01:00
orangecoding
fdd7e835e8 improve default puppeteer timeout 2026-02-18 20:06:22 +01:00
Christian Kellner
00d6a12b30 Puppeteer improvements (#270)
* improve puppeteer handling. Now only 1 puppeteer instance is being used which is WAY more efficient

* removing package-lock

* reduce logging

* removing problematic docker command

* Remove Immonet. They now belong to immowelt
2026-02-18 20:05:02 +01:00
orangecoding
fd7e228972 adding welcome screen 2026-02-17 12:35:39 +01:00
orangecoding
b86e351007 fixing lint even harder 2026-02-16 13:50:50 +01:00
orangecoding
10e40e038e adding check if fredy is running in docker 2026-02-16 12:29:02 +01:00
orangecoding
248e4d2562 improve tracking 2026-02-04 14:41:55 +01:00
orangecoding
7b8e961b49 adding confirmation dialog if to remove listing entirely from db or just hide it 2026-02-03 14:04:40 +01:00
orangecoding
0663bd945f smaller demo improvements 2026-01-29 09:46:23 +01:00
orangecoding
bc355fb5fe fixing some bugs the wife found ;) 2026-01-28 21:25:48 +01:00
orangecoding
797421f0d5 hardening demo handling 2026-01-28 16:29:59 +01:00