mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
🕵️ 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
This commit is contained in:
@@ -46,7 +46,9 @@ import {
|
||||
convertWebToMobile,
|
||||
} from '../services/immoscout/immoscout-web-translator.js';
|
||||
import logger from '../services/logger.js';
|
||||
import { getUserSettings } from '../services/storage/settingsStorage.js';
|
||||
let appliedBlackList = [];
|
||||
let currentUserId = null;
|
||||
|
||||
async function getListings(url) {
|
||||
const response = await fetch(url, {
|
||||
@@ -66,23 +68,86 @@ async function getListings(url) {
|
||||
}
|
||||
|
||||
const responseBody = await response.json();
|
||||
return responseBody.resultListItems
|
||||
.filter((item) => item.type === 'EXPOSE_RESULT')
|
||||
.map((expose) => {
|
||||
const item = expose.item;
|
||||
const [price, size] = item.attributes;
|
||||
const image = item?.titlePicture?.preview ?? null;
|
||||
return {
|
||||
id: item.id,
|
||||
price: price?.value,
|
||||
size: size?.value,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
link: `${metaInformation.baseUrl}expose/${item.id}`,
|
||||
address: item.address?.line,
|
||||
image,
|
||||
};
|
||||
});
|
||||
return Promise.all(
|
||||
responseBody.resultListItems
|
||||
.filter((item) => item.type === 'EXPOSE_RESULT')
|
||||
.map(async (expose) => {
|
||||
const item = expose.item;
|
||||
const [price, size] = item.attributes;
|
||||
const image = item?.titlePicture?.full ?? item?.titlePicture?.preview ?? null;
|
||||
let listing = {
|
||||
id: item.id,
|
||||
price: price?.value,
|
||||
size: size?.value,
|
||||
title: item.title,
|
||||
link: `${metaInformation.baseUrl}expose/${item.id}`,
|
||||
address: item.address?.line,
|
||||
image,
|
||||
};
|
||||
if (currentUserId) {
|
||||
const userSettings = getUserSettings(currentUserId);
|
||||
if (userSettings.immoscout_details) {
|
||||
return await pushDetails(listing);
|
||||
}
|
||||
}
|
||||
return listing;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function pushDetails(listing) {
|
||||
const detailed = await fetch(`https://api.mobile.immobilienscout24.de/expose/${listing.id}`, {
|
||||
headers: {
|
||||
'User-Agent': 'ImmoScout_27.3_26.0_._',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (!detailed.ok) {
|
||||
logger.error('Error fetching listing details from ImmoScout Mobile API:', detailed.statusText);
|
||||
return listing;
|
||||
}
|
||||
const detailBody = await detailed.json();
|
||||
|
||||
listing.description = buildDescription(detailBody);
|
||||
|
||||
return listing;
|
||||
}
|
||||
|
||||
function buildDescription(detailBody) {
|
||||
const sections = detailBody.sections || [];
|
||||
const contact = detailBody.contact || {};
|
||||
const cData = contact?.contactData || {};
|
||||
const agentName = cData?.agent?.name || '';
|
||||
const agentCompany = cData?.agent?.company || '';
|
||||
const stars = cData?.agent?.rating?.numberOfStars || '';
|
||||
const phoneNumbers = contact?.phoneNumbers || [];
|
||||
const phoneNumbersMapped = phoneNumbers
|
||||
.map((p) => `${p.label}: ${p.text}`)
|
||||
.join('\n')
|
||||
.trim();
|
||||
|
||||
const attributes = sections
|
||||
.filter((s) => s.type === 'ATTRIBUTE_LIST')
|
||||
.flatMap((s) => s.attributes)
|
||||
.filter((attr) => attr.label && attr.text)
|
||||
.map((attr) => `${attr.label} ${attr.text}`)
|
||||
.join('\n');
|
||||
|
||||
const freeText = sections
|
||||
.filter((s) => s.type === 'TEXT_AREA')
|
||||
.map((s) => {
|
||||
return `${s.title}\n${s.text}`;
|
||||
})
|
||||
.join('\n\n');
|
||||
|
||||
return (
|
||||
`Agent: ${agentName ? agentName : 'Unbekannt'} ${agentCompany ? `(${agentCompany}) ` : ''}${stars ? `- ${stars} stars` : ''}\n` +
|
||||
(phoneNumbersMapped ? `Phone Numbers:\n${phoneNumbersMapped}` : '') +
|
||||
'\n\n' +
|
||||
attributes.trim() +
|
||||
'\n\n' +
|
||||
freeText.trim()
|
||||
);
|
||||
}
|
||||
|
||||
async function isListingActive(link) {
|
||||
@@ -137,6 +202,7 @@ export const init = (sourceConfig, blacklist) => {
|
||||
config.enabled = sourceConfig.enabled;
|
||||
config.url = convertWebToMobile(sourceConfig.url);
|
||||
appliedBlackList = blacklist || [];
|
||||
currentUserId = sourceConfig.userId || null;
|
||||
};
|
||||
export const metaInformation = {
|
||||
name: 'Immoscout',
|
||||
|
||||
Reference in New Issue
Block a user