mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
217 lines
9.6 KiB
JavaScript
217 lines
9.6 KiB
JavaScript
/*
|
|
* Copyright (c) 2026 by Christian Kellner.
|
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
|
*/
|
|
|
|
/*
|
|
Rent a flat
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-mieten?numberofrooms=1.0-10000.0&price=1.0-10000.0&livingspace=10.0-10000.0&pricetype=rentpermonth&enteredFrom=result_list
|
|
*/
|
|
|
|
/*
|
|
Rent a flat:
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-mieten?enteredFrom=one_step_search
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/list?numberofrooms=1.5-&searchId=d7c127d8-6630-49e8-a1dd-5ae04dad454d&sorting=standard&pagesize=20&livingspace=10-500&pagenumber=1&realestatetype=apartmentrent&priceType=calculatedtotalrent&price=1-10000&publishedafter=2025-05-14T09:11:54&channel=is24&searchType=region&geocodes=/de/nordrhein-westfalen/duesseldorf&features=adKeysAndStringValues,virtualTour,contactDetails,viareporting,nextgen,calculatedTotalRent,listingsInListFirstSummary,xxlListingType,quickfilters,grouping,projectsInAllRealestateTypes,fairPrice
|
|
*/
|
|
|
|
/*
|
|
Rent a house:
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/haus-mieten?enteredFrom=one_step_search
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/map/v3?publishedafter=2025-05-14T09:12:49&pagenumber=1&searchType=region&geocodes=/de/nordrhein-westfalen/duesseldorf&realEstateType=houserent&pagesize=300&features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&sorting=standard
|
|
*/
|
|
|
|
/*
|
|
buy a flat
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/wohnung-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0&livingspace=1.0-10000.0&enteredFrom=result_list
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/map/v3?features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&sorting=standard&realEstateType=apartmentbuy&pagesize=300&pagenumber=1&geocodes=/de/nordrhein-westfalen/duesseldorf&publishedafter=2025-05-14T09:14:43&searchType=region
|
|
*/
|
|
|
|
/*
|
|
Buy a house
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/duesseldorf/haus-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0E7&livingspace=1.0-10000.0&enteredFrom=result_list
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/map/v3?geocodes=/de/nordrhein-westfalen/duesseldorf&features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&searchType=region&realEstateType=housebuy&pagenumber=1&pagesize=300&sorting=standard&publishedafter=2025-05-14T09:16:28
|
|
*/
|
|
|
|
/*
|
|
Buy a house only in parts of a city
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/haus-kaufen?numberofrooms=1.0-10000.0&price=1.0-10000.0E7&livingspace=1.0-10000.0&geocodes=1276010037,1276010014,1276010012&enteredFrom=result_list
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/list?pagesize=20&pagenumber=1&features=adKeysAndStringValues,virtualTour,contactDetails,viareporting,grouping,nextgen,listingsInListFirstSummary,xxlListingType,quickfilters,fairPrice&sorting=standard&channel=is24&geocodes=/de/nordrhein-westfalen/duesseldorf/stadtbezirk-1&searchType=region&realestatetype=housebuy&publishedafter=2025-05-14T09:17:23
|
|
*/
|
|
|
|
/*
|
|
Buy a house with radius
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/radius/haus-kaufen?centerofsearchaddress=D%C3%BCsseldorf%3B%3B%3B%3B%3B%3B&numberofrooms=1.0-10000.0&price=1.0-1.0E7&livingspace=1.0-10000.0&geocoordinates=51.22496%3B6.77567%3B5.0&enteredFrom=result_list
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/home/search/total?pagenumber=1&pagesize=1&geocoordinates=51.224960;6.775670;4.0&sorting=standard&searchType=radius&features=adKeysAndStringValues,virtualTour,contactDetails,grouping,nextgen,listingsInListFirstSummary,xxlListingType,fairPrice&channel=is24&realestatetype=housebuy&publishedafter=2025-05-14T09:19:43
|
|
*/
|
|
|
|
/*
|
|
Buy a house with shape
|
|
Web:
|
|
https://www.immobilienscout24.de/Suche/shape/haus-kaufen?shape=eW1yd0hpZGloQGBJa1NfQWFsQG9Uc1ZvVmlDbHdAZ2BAaEBjfEB5U3NWY2NCa0RvWmpwQG1KYGdCeldqU3Z4QGBAbENvQmJWaGtA&numberofrooms=1.0-100000.0&price=1.0-1.0E7&livingspace=1.0-100000.0&enteredFrom=result_list#/
|
|
Mobile:
|
|
https://api.mobile.immobilienscout24.de/search/map/v3?features=disableNHBGrouping,nextGen,fairPrice,listingsInListFirstSummary,xxlListingType,contactDetails&publishedafter=2025-05-14T09:19:43&sorting=standard&pagesize=300&searchType=shape&realEstateType=housebuy&pagenumber=1&shape=%7D%7BjwHy%7Cqh@jCKdCgAvB_BdB%7DBzAaCjAqCfAqC~@uCt@iCh@eCZkCLyC?_EO%7DEa@%7DEa@iE_@%7BD%5DaDe@gDi@gDo@uCu@kBcB_AeDOiE?iDCgCMuBOkDCkG?yFRgD%60@cB%5C%7BA%60@eBx@aB%7C@kAbAy@rAe@bBUxCAhE?dFh@fGlAzGbBbHlBxGdB%60FrAhDz@xBh@nAf@l@RNNXkCkMJR~B%7CEnCpErCnDtClCvC~ApCh@rCJpC?
|
|
*/
|
|
import queryString from 'query-string';
|
|
import { nullOrEmpty } from '../../utils.js';
|
|
|
|
const PARAM_NAME_MAP = {
|
|
heatingtypes: 'heatingtypes',
|
|
haspromotion: 'haspromotion',
|
|
numberofrooms: 'numberofrooms',
|
|
livingspace: 'livingspace',
|
|
energyefficiencyclasses: 'energyefficiencyclasses',
|
|
exclusioncriteria: 'exclusioncriteria',
|
|
equipment: 'equipment',
|
|
petsallowedtypes: 'petsallowedtypes',
|
|
price: 'price',
|
|
constructionyear: 'constructionyear',
|
|
apartmenttypes: 'apartmenttypes',
|
|
pricetype: 'pricetype',
|
|
floor: 'floor',
|
|
geocodes: 'geocodes',
|
|
geocoordinates: 'geocoordinates',
|
|
shape: 'shape',
|
|
sorting: 'sorting',
|
|
newbuilding: 'newbuilding',
|
|
};
|
|
|
|
const EQUIPMENT_MAP = {
|
|
parking: 'parking',
|
|
cellar: 'cellar',
|
|
builtinkitchen: 'builtInKitchen',
|
|
lift: 'lift',
|
|
garden: 'garden',
|
|
guesttoilet: 'guestToilet',
|
|
balcony: 'balcony',
|
|
handicappedaccessible: 'handicappedAccessible',
|
|
};
|
|
|
|
const REAL_ESTATE_TYPE = {
|
|
'haus-mieten': 'houserent',
|
|
'wohnung-mieten': 'apartmentrent',
|
|
'wohnung-kaufen': 'apartmentbuy',
|
|
'wohnung-kaufen-mit-balkon': 'apartmentbuy',
|
|
'eigentumswohnung-mit-garten': 'apartmentbuy',
|
|
'haus-kaufen': 'housebuy',
|
|
};
|
|
|
|
const WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP = {
|
|
// Category "Balkon/Terrasse"
|
|
'wohnung-mit-balkon-mieten': { equipment: ['balcony'] },
|
|
'wohnung-kaufen-mit-balkon': { equipment: ['balcony'] },
|
|
'wohnung-mit-garten-mieten': { equipment: ['garden'] },
|
|
'eigentumswohnung-mit-garten': { equipment: ['garden'] },
|
|
// Category "Wohnungstyp"
|
|
'souterrainwohnung-mieten': { apartmenttypes: ['halfbasement'] },
|
|
'erdgeschosswohnung-mieten': { apartmenttypes: ['groundfloor'] },
|
|
'hochparterrewohnung-mieten': { apartmenttypes: ['raisedgroundfloor'] },
|
|
'etagenwohnung-mieten': { apartmenttypes: ['apartment'] },
|
|
'loft-mieten': { apartmenttypes: ['loft'] },
|
|
'maisonette-mieten': { apartmenttypes: ['maisonette'] },
|
|
'terrassenwohnung-mieten': { apartmenttypes: ['terracedflat'] },
|
|
'penthouse-mieten': { apartmenttypes: ['penthouse'] },
|
|
'dachgeschosswohnung-mieten': { apartmenttypes: ['roofstorey'] },
|
|
// Category "Ausstattung"
|
|
'wohnung-mit-garage-mieten': { equipment: ['parking'] },
|
|
'wohnung-mit-einbaukueche-mieten': { equipment: ['builtinkitchen'] },
|
|
'wohnung-mit-keller-mieten': { equipment: ['cellar'] },
|
|
// Category "Merkmale"
|
|
'neubauwohnung-mieten': { newbuilding: true },
|
|
'barrierefreie-wohnung-mieten': { equipment: ['handicappedaccessible'] },
|
|
};
|
|
|
|
export function convertWebToMobile(webUrl) {
|
|
let url;
|
|
try {
|
|
url = new URL(webUrl);
|
|
} catch {
|
|
throw new Error(`Invalid URL: ${webUrl}`);
|
|
}
|
|
|
|
const segments = url.pathname.split('/');
|
|
if (segments[1] !== 'Suche') {
|
|
throw new Error(`Unexpected path format: ${url.pathname}. We're expecting to see "/Suche" in the path.`);
|
|
}
|
|
|
|
const realTypeKey = segments.at(-1);
|
|
let realType = REAL_ESTATE_TYPE[realTypeKey];
|
|
let additionalParamsFromWebPath = WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey] || null;
|
|
|
|
if (!realType) {
|
|
// Test for seo optimized apartment path (only used on the ImmoScout web app)
|
|
if (WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey]) {
|
|
additionalParamsFromWebPath = WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey];
|
|
realType = REAL_ESTATE_TYPE['wohnung-mieten'];
|
|
} else {
|
|
throw new Error(`Real estate type not found: ${realTypeKey}`);
|
|
}
|
|
}
|
|
|
|
if (segments.includes('shape')) {
|
|
throw new Error('Shape is currently not supported using Immoscout');
|
|
}
|
|
|
|
const { query: rawParams } = queryString.parseUrl(webUrl, { arrayFormat: 'comma' });
|
|
const webParams = Object.fromEntries(
|
|
Object.entries(rawParams).filter(([key]) => key !== 'enteredFrom' && PARAM_NAME_MAP[key]),
|
|
);
|
|
|
|
const geocodes = `/${segments.slice(2, segments.length - 1).join('/')}`;
|
|
const isRadius = segments.includes('radius');
|
|
const mobileParams = {
|
|
searchType: isRadius ? 'radius' : 'region',
|
|
realestatetype: realType,
|
|
...(isRadius ? {} : { geocodes }),
|
|
...additionalParamsFromWebPath,
|
|
};
|
|
|
|
if (webParams.geocoordinates) {
|
|
mobileParams.geocoordinates = webParams.geocoordinates;
|
|
}
|
|
|
|
for (const [key, val] of Object.entries(webParams)) {
|
|
if (key === 'equipment') {
|
|
const items = [].concat(val).flatMap((v) => `${v}`.split(','));
|
|
const currentEquipmentParams = mobileParams[PARAM_NAME_MAP[key]];
|
|
mobileParams[PARAM_NAME_MAP[key]] = [
|
|
...(currentEquipmentParams ?? []),
|
|
...items.map((item) => EQUIPMENT_MAP[item.toLowerCase()]).filter(Boolean),
|
|
];
|
|
} else {
|
|
mobileParams[PARAM_NAME_MAP[key]] = val;
|
|
}
|
|
}
|
|
|
|
const mobileQuery = queryString.stringify(mobileParams, {
|
|
arrayFormat: 'comma',
|
|
encode: true,
|
|
skipEmptyString: true,
|
|
});
|
|
|
|
return `https://api.mobile.immobilienscout24.de/search/list?${mobileQuery}`;
|
|
}
|
|
|
|
export function convertImmoscoutListingToMobileListing(url) {
|
|
if (nullOrEmpty(url)) {
|
|
return null;
|
|
}
|
|
|
|
return url.replace(
|
|
/^https:\/\/www\.immobilienscout24\.de\/expose\//,
|
|
'https://api.mobile.immobilienscout24.de/expose/',
|
|
);
|
|
}
|