Skip to content

Commit

Permalink
fix: Remove price per m2 from rental ads
Browse files Browse the repository at this point in the history
Added logic to check if ad is type of RENT and when yes omit price per m2 extraction

Removed location.hostname passing from contentscript to sites

Small refactorings

Fixes realreality#74
  • Loading branch information
vire committed Mar 31, 2017
1 parent 2afd012 commit 5b50057
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 39 deletions.
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
87 changes: 62 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,91 @@ 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.SREALITY.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 +103,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 +117,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 +127,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

0 comments on commit 5b50057

Please sign in to comment.