Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Remove price per m2 from rental ads #76

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/js/contentscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import App from './components/App.vue';
RR.logInfo('contentscript loaded');

chrome.runtime.sendMessage({ 'switchIconOn': true });
const POLL_ADDRESS_TIMEOUT = 500;

const initVueTranslations = () => {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -66,7 +67,7 @@ const loadPanel = function(address) {
address,
details: {
price: {
perSquareMeter: pageDataExtractor.getPrices(window.location.host)
perSquareMeter: pageDataExtractor.extractSquarePrice()
}
}
}
Expand All @@ -78,7 +79,7 @@ const loadPanel = function(address) {
let addressOfProperty;
function initApp() {
RR.logInfo('Initializing app widget');
addressOfProperty = pageDataExtractor.getAddress(window.location.host);
addressOfProperty = pageDataExtractor.getAddress();
RR.logDebug('Address parsed: ', addressOfProperty);

if (RR.String.isNotBlank(addressOfProperty)) {
Expand All @@ -94,13 +95,13 @@ function initApp() {
let pollAddressTimerId;
function pollAddress() {
//RR.logDebug('Polling address...'); // you can filter it out in console with regexp filter ^(?=.*?\b.*\b)((?!Poll).)*$ (match all except lines with 'Poll' match)
const currentAddressOfProperty = pageDataExtractor.getAddress(window.location.host);
const currentAddressOfProperty = pageDataExtractor.getAddress();
//RR.logDebug('Polled address:', currentAddressOfProperty);
if (currentAddressOfProperty !== addressOfProperty) {
$(document).trigger(RR.ADDRESS_CHANGED_EVENT);
clearTimeout(pollAddressTimerId);
}
pollAddressTimerId = setTimeout(pollAddress, 500);
pollAddressTimerId = setTimeout(pollAddress, POLL_ADDRESS_TIMEOUT);
}

$(document).on(RR.ADDRESS_CHANGED_EVENT, (event) => {
Expand Down
86 changes: 61 additions & 25 deletions src/js/sites/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const RENT = 'rent';
const SALE = 'sale';

const textOrNull = textElement => {
if (textElement === null) {
return null;
Expand All @@ -6,57 +9,90 @@ const textOrNull = textElement => {
}
};

export const siteHosts = {
const sites = {
SREALITY: {
hostString: 'sreality.cz'
id: 'sreality',
},
BEZREALITKY: {
hostString: 'bezrealitky.cz'
id: 'bezrealitky',
},
MAXIREALITY: {
hostString: 'maxirealitypraha.cz'
id: 'maxirealitypraha',
},
REALITY_IDNES: {
hostString: 'reality.idnes.cz'
id: 'idnes',
}
};

/**
*
* @param {{ hostString: String }} hostId
* @param {String} host
* @return {Number|undefined}
*/
export const isCurrentHost = (hostId, host) => host.includes(hostId.hostString);

const priceAreaGuard = (price, area) => (area && !isNaN(area) && (price && !isNaN(price))) && price / area;

const getHostPredicate = (locationHost) => (siteHost) => locationHost.includes(siteHost);

const containsBoxWords = (selector, words) => {
const containsNodeWord = (node, word) => node.textContent.includes(word);

const node = document.querySelector(selector);
if (!node || !words.length) {
return false;
}

const mapWords = (word) => containsNodeWord(node, word);
// ['foo'] => [true]
// ['foo', 'bar', 'baz'] => [true, false, true] => false
return words.map(mapWords).filter(Boolean).length === words.length;
};

// this is business logic, so it may contain site specific settings/params
// underneath it should only call some generic functions
const extractAdType = (locationHost) => {
const verify = getHostPredicate(locationHost);

if (verify(sites.REALITY_IDNES.id) || verify(sites.SREALITY.id) || verify(sites.MAXIREALITY.id)) {
if (/pronajem/i.test(location.pathname)) {
return RENT;
}
return SALE;
}

if (verify('bezrealitky')) {
const selector = '.box-params.col-1';
return containsBoxWords(selector, ['typ', 'nabídky', 'Pronájem']) ? RENT : SALE;
}
};

// TODO add extractor's methods for sites dynamically
export const extractors = {
getAddress(host) {
if (isCurrentHost(siteHosts.SREALITY, host)) {
getAddress() {
const verify = getHostPredicate(window.location.host);
if (verify(sites.SREALITY.id)) {
return textOrNull(document.querySelector('.location-text'));
}

if (isCurrentHost(siteHosts.BEZREALITKY, host)) {
if (verify(sites.BEZREALITKY.id)) {
return textOrNull(document.querySelector('header h2'));
}

if (isCurrentHost(siteHosts.MAXIREALITY, host)) {
if (verify(sites.MAXIREALITY.id)) {
const addressRow = Array.from(document.querySelectorAll('tr'))
.filter(node => node.textContent.includes('Adresa'))[0];
return addressRow && addressRow.querySelector('td').innerHTML.replace(/<br>/g, ' ').trim();
}

if (isCurrentHost(siteHosts.REALITY_IDNES, host)) {
if (verify(sites.REALITY_IDNES.id)) {
return textOrNull(document.querySelector('.realAddress'));
}

RR.logError('cannot parse address on page: ', window.location);
return null;
},
getPrices(host) {
if (isCurrentHost(siteHosts.SREALITY, host)) {
extractSquarePrice() {
const adType = extractAdType(window.location.host);
const verify = getHostPredicate(window.location.host);
if (adType === RENT) {
return;
}

if (verify(sites.SREALITY.id)) {
const propertyParams = Array.from(document.querySelectorAll('.params li'));
const priceRow = propertyParams.filter(p => p.innerHTML.includes('Celková cena'))[0];
const areaRow = propertyParams.filter(p => p.innerHTML.includes('Užitná'))[0];
Expand All @@ -66,7 +102,7 @@ export const extractors = {
return priceAreaGuard(price, area);
}

if (isCurrentHost(siteHosts.BEZREALITKY, host)) {
if (verify(sites.BEZREALITKY.id)) {
const propertyParams = Array.from(document.querySelectorAll('.box-params .row'));
const areaRow = propertyParams.filter(item => item.innerHTML.includes('plocha'))[0]; // returns DOM node
const priceRow = propertyParams.filter(item => item.innerHTML.includes('cena'))[0]; // returns DOM node
Expand All @@ -80,7 +116,7 @@ export const extractors = {
return priceAreaGuard(price, area);
}

if (isCurrentHost(siteHosts.MAXIREALITY, host)) {
if (verify(sites.MAXIREALITY.id)) {
const areaRow = Array.from(document.querySelectorAll('#makler_zaklad > table tr'))
.filter(node => node.innerHTML.includes('Užitná plocha'))[0];
const priceNode = document.querySelector('.two.price');
Expand All @@ -90,12 +126,12 @@ export const extractors = {
return priceAreaGuard(price, area);
}

if (isCurrentHost(siteHosts.REALITY_IDNES, host)) {
if (verify(sites.REALITY_IDNES.id)) {
const areaText = $('.parameters .leftCol dt:contains("Užitná plocha")').next().text();
const area = Number.parseInt(areaText); // eg. when text is "34 m2" Number.parseInt can strip text parts and parse it as just 34

const priceText = document.querySelectorAll('.priceBox strong')[0].innerHTML;
const price = Number.parseInt(priceText.replace(/&nbsp;/gi,''));
const priceText = document.querySelectorAll('.priceBox strong')[0].innerHTML;
const price = Number.parseInt(priceText.replace(/&nbsp;/gi, ''));

return priceAreaGuard(price, area);
}
Expand Down
16 changes: 8 additions & 8 deletions src/js/sites/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ describe('extractors', () => {
});

it('should return price per m2', () => {
expect(extractors.getPrices(window.location.host)).to.equal(22222.222222222223);
expect(extractors.extractSquarePrice()).to.equal(22222.222222222223);
});

it('should return address', () => {
expect(extractors.getAddress(window.location.host)).to.equal('Komenského, Vlašim, Středočeský kraj');
expect(extractors.getAddress()).to.equal('Komenského, Vlašim, Středočeský kraj');
});
});

Expand All @@ -43,11 +43,11 @@ describe('extractors', () => {
});

it('should return price per m2', () => {
expect(extractors.getPrices(window.location.host)).to.equal(57042.25352112676);
expect(extractors.extractSquarePrice()).to.equal(57042.25352112676);
});

it('should return address', () => {
expect(extractors.getAddress(window.location.host)).to.equal('Ortenovo náměstí, Praha 7 - Holešovice');
expect(extractors.getAddress()).to.equal('Ortenovo náměstí, Praha 7 - Holešovice');
});
});

Expand All @@ -61,11 +61,11 @@ describe('extractors', () => {
});

it('should return price per m2', () => {
expect(extractors.getPrices(window.location.host)).to.equal(64805.194805194806);
expect(extractors.extractSquarePrice()).to.equal(64805.194805194806);
});

it('should return address', () => {
expect(extractors.getAddress(window.location.host)).to.equal('Praha - Smíchov Vrázova');
expect(extractors.getAddress()).to.equal('Praha - Smíchov Vrázova');
});
});

Expand All @@ -83,11 +83,11 @@ describe('extractors', () => {
});

it('should return price per m2', () => {
expect(extractors.getPrices(window.location.host)).to.equal(31888.88888888889);
expect(extractors.extractSquarePrice()).to.equal(31888.88888888889);
});

it('should return address', () => {
expect(extractors.getAddress(window.location.host)).to.equal('Praha 5, Hlubočepy, Machatého');
expect(extractors.getAddress()).to.equal('Praha 5, Hlubočepy, Machatého');
});
});
});
9 changes: 8 additions & 1 deletion src/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ export const streetNamePredicate = (address) => {
return address;
};

export const formatPrice = price => Math.round(price) + ' Kč';
export const formatPrice = price => {
const formatter = new Intl.NumberFormat('cs', {
style: 'currency',
currency: 'CZK',
minimumFractionDigits: 0,
});
return formatter.format(Math.round(price));
};

/**
* Call ga (google analytics) in context of current page - we cannot directly call page functions here
Expand Down
1 change: 0 additions & 1 deletion src/templates/panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<!-- Google Analytics from Real Reality Chrome Extension -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;

ga('create', 'UA-85464417-1', 'auto', 'rr');
ga('rr.send', 'pageview');
</script>
Expand Down