Kompletan spisak nekretnina možete pegledati ovdije:
Nekretnine
`;
diff --git a/app/helpers/codes.js b/app/helpers/codes.js
index bcec456..ac589d4 100644
--- a/app/helpers/codes.js
+++ b/app/helpers/codes.js
@@ -1,928 +1,931 @@
const regions = [
- {
- "name": " Sarajevo",
- "id": "sarajevo",
- "olxid": "9",
- "municipalities": [
- {
- "name": "Hadžići",
- "id": "hadii",
- "olxid": "3817"
- },
- {
- "name": "Ilidža",
- "id": "ilida",
- "olxid": "3879"
- },
- {
- "name": "Ilijaš",
- "id": "ilija",
- "olxid": "3892"
- },
- {
- "name": "Sarajevo - Centar",
- "id": "sarajevocentar",
- "olxid": "3812"
- },
- {
- "name": "Sarajevo-Novi Grad",
- "id": "sarajevonovigrad",
- "olxid": "3969"
- },
- {
- "name": "Sarajevo-Novo Sarajevo",
- "id": "sarajevonovosarajevo",
- "olxid": "5896"
- },
- {
- "name": "Sarajevo-Stari Grad",
- "id": "sarajevostarigrad",
- "olxid": "4048"
- },
- {
- "name": "Trnovo",
- "id": "trnovo",
- "olxid": "4063"
- },
- {
- "name": "Vogošća",
- "id": "vogoa",
- "olxid": "4126"
- }
- ]
- },
- {
- "name": " Unsko-sanski",
- "id": "unskosanski",
- "olxid": "9",
- "municipalities": [
- {
- "name": "Bihać",
- "id": "biha",
- "olxid": "75"
- },
- {
- "name": "Bosanska Krupa",
- "id": "bosanskakrupa",
- "olxid": "373"
- },
- {
- "name": "Bosanski Petrovac",
- "id": "bosanskipetrovac",
- "olxid": "504"
- },
- {
- "name": "Bužim",
- "id": "buim",
- "olxid": "374"
- },
- {
- "name": "Cazin",
- "id": "cazin",
- "olxid": "857"
- },
- {
- "name": "Ključ",
- "id": "klju",
- "olxid": "2362"
- },
- {
- "name": "Sanski Most",
- "id": "sanskimost",
- "olxid": "3738"
- },
- {
- "name": "Velika Kladuša",
- "id": "velikakladua",
- "olxid": "5122"
- }
- ]
- },
- {
- "name": " Posavski",
- "id": "posavski",
- "olxid": "15",
- "municipalities": [
- {
- "name": "Domaljevac",
- "id": "domaljevac",
- "olxid": "6144"
- },
- {
- "name": "Odžak",
- "id": "odak",
- "olxid": "424"
- },
- {
- "name": "Orašje",
- "id": "oraje",
- "olxid": "3252"
- },
- {
- "name": "Šamac",
- "id": "amac",
- "olxid": "540"
- }
- ]
- },
- {
- "name": " Tuzlanski",
- "id": "tuzlanski",
- "olxid": "15",
- "municipalities": [
- {
- "name": "Banovići",
- "id": "banovii",
- "olxid": "2"
- },
- {
- "name": "Doboj-Istok",
- "id": "dobojistok",
- "olxid": "1090"
- },
- {
- "name": "Gradačac",
- "id": "gradaac",
- "olxid": "1854"
- },
- {
- "name": "Gračanica",
- "id": "graanica",
- "olxid": "1826"
- },
- {
- "name": "Kalesija",
- "id": "kalesija",
- "olxid": "2129"
- },
- {
- "name": "Kladanj",
- "id": "kladanj",
- "olxid": "2319"
- },
- {
- "name": "Lukavac",
- "id": "lukavac",
- "olxid": "2840"
- },
- {
- "name": "Sapna",
- "id": "sapna",
- "olxid": "5699"
- },
- {
- "name": "Srebrenik",
- "id": "srebrenik",
- "olxid": "4391"
- },
- {
- "name": "Teočak",
- "id": "teoak",
- "olxid": "5010"
- },
- {
- "name": "Tuzla",
- "id": "tuzla",
- "olxid": "4944"
- },
- {
- "name": "Čelić",
- "id": "eli",
- "olxid": "2801"
- },
- {
- "name": "Živinice",
- "id": "ivinice",
- "olxid": "5774"
- }
- ]
- },
- {
- "name": " Zeničko-dobojski",
- "id": "zenickodobojski",
- "olxid": "15",
- "municipalities": [
- {
- "name": "Breza",
- "id": "breza",
- "olxid": "704"
- },
- {
- "name": "Doboj-Jug",
- "id": "dobojjug",
- "olxid": "1122"
- },
- {
- "name": "Kakanj",
- "id": "kakanj",
- "olxid": "2022"
- },
- {
- "name": "Maglaj",
- "id": "maglaj",
- "olxid": "2941"
- },
- {
- "name": "Olovo",
- "id": "olovo",
- "olxid": "1925"
- },
- {
- "name": "Tešanj",
- "id": "teanj",
- "olxid": "4594"
- },
- {
- "name": "Usora",
- "id": "usora",
- "olxid": "1087"
- },
- {
- "name": "Vareš",
- "id": "vare",
- "olxid": "5037"
- },
- {
- "name": "Visoko",
- "id": "visoko",
- "olxid": "5171"
- },
- {
- "name": "Zavidovići",
- "id": "zavidovii",
- "olxid": "5548"
- },
- {
- "name": "Zenica",
- "id": "zenica",
- "olxid": "4571"
- },
- {
- "name": "Žepče",
- "id": "epe",
- "olxid": "2940"
- }
- ]
- },
- {
- "name": " Bosansko-podrinjski",
- "id": "bosanskopodrinjski",
- "olxid": "15",
- "municipalities": [
- {
- "name": "Foča",
- "id": "foa",
- "olxid": "1289"
- },
- {
- "name": "Goražde",
- "id": "gorade",
- "olxid": "1588"
- },
- {
- "name": "Pale",
- "id": "pale",
- "olxid": "3546"
- }
- ]
- },
- {
- "name": " Srednjobosanski",
- "id": "srednjobosanski",
- "olxid": "6",
- "municipalities": [
- {
- "name": "Bugojno",
- "id": "bugojno",
- "olxid": "732"
- },
- {
- "name": "Busovača",
- "id": "busovaa",
- "olxid": "810"
- },
- {
- "name": "Dobretići",
- "id": "dobretii",
- "olxid": "4151"
- },
- {
- "name": "Donji Vakuf",
- "id": "donjivakuf",
- "olxid": "1160"
- },
- {
- "name": "Fojnica",
- "id": "fojnica",
- "olxid": "1407"
- },
- {
- "name": "Gornji Vakuf - Uskoplje",
- "id": "gornjivakufuskoplje",
- "olxid": "1775"
- },
- {
- "name": "Jajce",
- "id": "jajce",
- "olxid": "1960"
- },
- {
- "name": "Kiseljak",
- "id": "kiseljak",
- "olxid": "2237"
- },
- {
- "name": "Kreševo",
- "id": "kreevo",
- "olxid": "2608"
- },
- {
- "name": "Novi Travnik",
- "id": "novitravnik",
- "olxid": "3477"
- },
- {
- "name": "Travnik",
- "id": "travnik",
- "olxid": "4678"
- },
- {
- "name": "Vitez",
- "id": "vitez",
- "olxid": "5422"
- }
- ]
- },
- {
- "name": " Hercegovačko-neretvanski",
- "id": "hercegovackoneretvanski",
- "olxid": "7",
- "municipalities": [
- {
- "name": "Grad Mostar",
- "id": "gradmostar",
- "olxid": "3017"
- },
- {
- "name": "Jablanica",
- "id": "jablanica",
- "olxid": "1930"
- },
- {
- "name": "Konjic",
- "id": "konjic",
- "olxid": "2169"
- },
- {
- "name": "Neum",
- "id": "neum",
- "olxid": "3111"
- },
- {
- "name": "Prozor",
- "id": "prozor",
- "olxid": "3421"
- },
- {
- "name": "Ravno",
- "id": "ravno",
- "olxid": "4769"
- },
- {
- "name": "Stolac",
- "id": "stolac",
- "olxid": "4439"
- },
- {
- "name": "Čapljina",
- "id": "apljina",
- "olxid": "947"
- },
- {
- "name": "Čitluk",
- "id": "itluk",
- "olxid": "1009"
- }
- ]
- },
- {
- "name": " Zapadno-hercegovački",
- "id": "zapadnohercegovacki",
- "olxid": "8",
- "municipalities": [
- {
- "name": "Grude",
- "id": "grude",
- "olxid": "1892"
- },
- {
- "name": "Ljubuški",
- "id": "ljubuki",
- "olxid": "2905"
- },
- {
- "name": "Posušje",
- "id": "posuje",
- "olxid": "3268"
- },
- {
- "name": "Široki Brijeg",
- "id": "irokibrijeg",
- "olxid": "2708"
- }
- ]
- },
- {
- "name": " Livanjski",
- "id": "livanjski",
- "olxid": "10",
- "municipalities": [
- {
- "name": "Bosansko Grahovo",
- "id": "bosanskograhovo",
- "olxid": "560"
- },
- {
- "name": "Drvar",
- "id": "drvar",
- "olxid": "4640"
- },
- {
- "name": "Glamoč",
- "id": "glamo",
- "olxid": "1533"
- },
- {
- "name": "Kupres",
- "id": "kupres",
- "olxid": "2635"
- },
- {
- "name": "Livno",
- "id": "livno",
- "olxid": "2741"
- },
- {
- "name": "Tomislavgrad",
- "id": "tomislavgrad",
- "olxid": "1228"
- }
- ]
- },
- {
- "name": " Banjalučka",
- "id": "banjalučka",
- "olxid": "14",
- "municipalities": [
- {
- "name": "Banja Luka",
- "id": "banjaluka",
- "olxid": "21"
- },
- {
- "name": "Gradiška",
- "id": "gradika",
- "olxid": "305"
- },
- {
- "name": "Istočni Drvar",
- "id": "istonidrvar",
- "olxid": "4662"
- },
- {
- "name": "Jezero",
- "id": "jezero",
- "olxid": "1965"
- },
- {
- "name": "Kneževo",
- "id": "kneevo",
- "olxid": "4147"
- },
- {
- "name": "Kostajnica",
- "id": "kostajnica",
- "olxid": "6142"
- },
- {
- "name": "Kotor Varoš",
- "id": "kotorvaro",
- "olxid": "2574"
- },
- {
- "name": "Kozarska Dubica",
- "id": "kozarskadubica",
- "olxid": "244"
- },
- {
- "name": "Krupa na uni",
- "id": "krupanauni",
- "olxid": "382"
- },
- {
- "name": "Kupres ",
- "id": "kupres",
- "olxid": "2654"
- },
- {
- "name": "Laktaši",
- "id": "laktai",
- "olxid": "2671"
- },
- {
- "name": "Mrkonjić Grad",
- "id": "mrkonjigrad",
- "olxid": "3073"
- },
- {
- "name": "Novi Grad",
- "id": "novigrad",
- "olxid": "444"
- },
- {
- "name": "Oštra Luka",
- "id": "otraluka",
- "olxid": "3737"
- },
- {
- "name": "Petrovac",
- "id": "petrovac",
- "olxid": "515"
- },
- {
- "name": "Prijedor",
- "id": "prijedor",
- "olxid": "3287"
- },
- {
- "name": "Prnjavor",
- "id": "prnjavor",
- "olxid": "3358"
- },
- {
- "name": "Ribnik",
- "id": "ribnik",
- "olxid": "2365"
- },
- {
- "name": "Srbac",
- "id": "srbac",
- "olxid": "4271"
- },
- {
- "name": "Čelinac",
- "id": "elinac",
- "olxid": "979"
- },
- {
- "name": "Šipovo",
- "id": "ipovo",
- "olxid": "4509"
- }
- ]
- },
- {
- "name": " Dobojsko-Bijeljinska",
- "id": "dobojskobijeljinska",
- "olxid": "15",
- "municipalities": [
- {
- "name": "Bijeljina",
- "id": "bijeljina",
- "olxid": "123"
- },
- {
- "name": "Bosanski Brod",
- "id": "bosanskibrod",
- "olxid": "421"
- },
- {
- "name": "Derventa",
- "id": "derventa",
- "olxid": "1030"
- },
- {
- "name": "Doboj",
- "id": "doboj",
- "olxid": "1088"
- },
- {
- "name": "Donji Žabar",
- "id": "donjiabar",
- "olxid": "3254"
- },
- {
- "name": "Lopare",
- "id": "lopare",
- "olxid": "2800"
- },
- {
- "name": "Lukavac",
- "id": "lukavac",
- "olxid": "6029"
- },
- {
- "name": "Modriča",
- "id": "modria",
- "olxid": "2996"
- },
- {
- "name": "Pelagićevo",
- "id": "pelagievo",
- "olxid": "1856"
- },
- {
- "name": "Petrovo",
- "id": "petrovo",
- "olxid": "1827"
- },
- {
- "name": "Stanari",
- "id": "stanari",
- "olxid": "1148"
- },
- {
- "name": "Teslić",
- "id": "tesli",
- "olxid": "4549"
- },
- {
- "name": "Tešanj",
- "id": "teanj",
- "olxid": "4636"
- },
- {
- "name": "Travnik",
- "id": "travnik",
- "olxid": "4692"
- },
- {
- "name": "Tuzla",
- "id": "tuzla",
- "olxid": "4966"
- },
- {
- "name": "Ugljevik",
- "id": "ugljevik",
- "olxid": "5009"
- },
- {
- "name": "Vukosavlje",
- "id": "vukosavlje",
- "olxid": "3197"
- },
- {
- "name": "Šamac",
- "id": "amac",
- "olxid": "539"
- }
- ]
- },
- {
- "name": " Sarajevsko-Zvornička",
- "id": "sarajevskozvornicka",
- "olxid": "16",
- "municipalities": [
- {
- "name": "Bratunac",
- "id": "bratunac",
- "olxid": "595"
- },
- {
- "name": "Han Pijesak",
- "id": "hanpijesak",
- "olxid": "1904"
- },
- {
- "name": "Ilijaš",
- "id": "ilija",
- "olxid": "3947"
- },
- {
- "name": "Istočni Stari Grad",
- "id": "istonistarigrad",
- "olxid": "4049"
- },
- {
- "name": "Kasindo",
- "id": "kasindo",
- "olxid": "3880"
- },
- {
- "name": "Kladanj",
- "id": "kladanj",
- "olxid": "2325"
- },
- {
- "name": "Lukavica",
- "id": "lukavica",
- "olxid": "3971"
- },
- {
- "name": "Milići",
- "id": "milii",
- "olxid": "6143"
- },
- {
- "name": "Olovo",
- "id": "olovo",
- "olxid": "3221"
- },
- {
- "name": "Osmaci",
- "id": "osmaci",
- "olxid": "2128"
- },
- {
- "name": "Pale",
- "id": "pale",
- "olxid": "3978"
- },
- {
- "name": "Rogatica",
- "id": "rogatica",
- "olxid": "3529"
- },
- {
- "name": "Rudo",
- "id": "rudo",
- "olxid": "3648"
- },
- {
- "name": "Sarajevo-Novi Grad",
- "id": "sarajevonovigrad",
- "olxid": "6069"
- },
- {
- "name": "Sokolac",
- "id": "sokolac",
- "olxid": "4183"
- },
- {
- "name": "Srebrenica",
- "id": "srebrenica",
- "olxid": "4310"
- },
- {
- "name": "Trnovo",
- "id": "trnovo",
- "olxid": "4067"
- },
- {
- "name": "Ustiprača",
- "id": "ustipraa",
- "olxid": "1593"
- },
- {
- "name": "Višegrad",
- "id": "viegrad",
- "olxid": "5259"
- },
- {
- "name": "Vlasenica",
- "id": "vlasenica",
- "olxid": "5456"
- },
- {
- "name": "Zvornik",
- "id": "zvornik",
- "olxid": "5684"
- },
- {
- "name": "Šekovići",
- "id": "ekovii",
- "olxid": "4475"
- },
- {
- "name": "Žepa",
- "id": "epa",
- "olxid": "1906"
- }
- ]
- },
- {
- "name": " Trebinjsko-Fočanska",
- "id": "trebinjskofocanska",
- "olxid": "17",
- "municipalities": [
- {
- "name": "Berkovići",
- "id": "berkovii",
- "olxid": "4441"
- },
- {
- "name": "Bileća",
- "id": "bilea",
- "olxid": "183"
- },
- {
- "name": "Foča",
- "id": "foa",
- "olxid": "1287"
- },
- {
- "name": "Gacko",
- "id": "gacko",
- "olxid": "1462"
- },
- {
- "name": "Istočni Mostar",
- "id": "istonimostar",
- "olxid": "3038"
- },
- {
- "name": "Kalinovik",
- "id": "kalinovik",
- "olxid": "2164"
- },
- {
- "name": "Ljubinje",
- "id": "ljubinje",
- "olxid": "2884"
- },
- {
- "name": "Nevesinje",
- "id": "nevesinje",
- "olxid": "3138"
- },
- {
- "name": "Trebinje",
- "id": "trebinje",
- "olxid": "4766"
- },
- {
- "name": "Čajniče",
- "id": "ajnie",
- "olxid": "911"
- }
- ]
- },
- {
- "name": "Distrikt Brčko",
- "id": "distriktbrcko",
- "olxid": "12",
- "municipalities": [
- {
- "name": "Brčko",
- "id": "brko",
- "olxid": "12"
- }
-
- ]
- }
+ {
+ name: " Sarajevo",
+ id: "sarajevo",
+ olxid: "9",
+ municipalities: [
+ {
+ name: "Hadžići",
+ id: "hadii",
+ olxid: "3817"
+ },
+ {
+ name: "Ilidža",
+ id: "ilida",
+ olxid: "3879"
+ },
+ {
+ name: "Ilijaš",
+ id: "ilija",
+ olxid: "3892"
+ },
+ {
+ name: "Sarajevo - Centar",
+ id: "sarajevocentar",
+ olxid: "3812"
+ },
+ {
+ name: "Sarajevo-Novi Grad",
+ id: "sarajevonovigrad",
+ olxid: "3969"
+ },
+ {
+ name: "Sarajevo-Novo Sarajevo",
+ id: "sarajevonovosarajevo",
+ olxid: "5896"
+ },
+ {
+ name: "Sarajevo-Stari Grad",
+ id: "sarajevostarigrad",
+ olxid: "4048"
+ },
+ {
+ name: "Trnovo",
+ id: "trnovo",
+ olxid: "4063"
+ },
+ {
+ name: "Vogošća",
+ id: "vogoa",
+ olxid: "4126"
+ }
+ ]
+ },
+ {
+ name: " Unsko-sanski",
+ id: "unskosanski",
+ olxid: "1",
+ municipalities: [
+ {
+ name: "Bihać",
+ id: "biha",
+ olxid: "75"
+ },
+ {
+ name: "Bosanska Krupa",
+ id: "bosanskakrupa",
+ olxid: "373"
+ },
+ {
+ name: "Bosanski Petrovac",
+ id: "bosanskipetrovac",
+ olxid: "504"
+ },
+ {
+ name: "Bužim",
+ id: "buim",
+ olxid: "374"
+ },
+ {
+ name: "Cazin",
+ id: "cazin",
+ olxid: "857"
+ },
+ {
+ name: "Ključ",
+ id: "klju",
+ olxid: "2362"
+ },
+ {
+ name: "Sanski Most",
+ id: "sanskimost",
+ olxid: "3738"
+ },
+ {
+ name: "Velika Kladuša",
+ id: "velikakladua",
+ olxid: "5122"
+ }
+ ]
+ },
+ {
+ name: " Posavski",
+ id: "posavski",
+ olxid: "2",
+ municipalities: [
+ {
+ name: "Domaljevac",
+ id: "domaljevac",
+ olxid: "6144"
+ },
+ {
+ name: "Odžak",
+ id: "odak",
+ olxid: "424"
+ },
+ {
+ name: "Orašje",
+ id: "oraje",
+ olxid: "3252"
+ },
+ {
+ name: "Šamac",
+ id: "amac",
+ olxid: "540"
+ }
+ ]
+ },
+ {
+ name: " Tuzlanski",
+ id: "tuzlanski",
+ olxid: "3",
+ municipalities: [
+ {
+ name: "Banovići",
+ id: "banovii",
+ olxid: "2"
+ },
+ {
+ name: "Doboj-Istok",
+ id: "dobojistok",
+ olxid: "1090"
+ },
+ {
+ name: "Gradačac",
+ id: "gradaac",
+ olxid: "1854"
+ },
+ {
+ name: "Gračanica",
+ id: "graanica",
+ olxid: "1826"
+ },
+ {
+ name: "Kalesija",
+ id: "kalesija",
+ olxid: "2129"
+ },
+ {
+ name: "Kladanj",
+ id: "kladanj",
+ olxid: "2319"
+ },
+ {
+ name: "Lukavac",
+ id: "lukavac",
+ olxid: "2840"
+ },
+ {
+ name: "Sapna",
+ id: "sapna",
+ olxid: "5699"
+ },
+ {
+ name: "Srebrenik",
+ id: "srebrenik",
+ olxid: "4391"
+ },
+ {
+ name: "Teočak",
+ id: "teoak",
+ olxid: "5010"
+ },
+ {
+ name: "Tuzla",
+ id: "tuzla",
+ olxid: "4944"
+ },
+ {
+ name: "Čelić",
+ id: "eli",
+ olxid: "2801"
+ },
+ {
+ name: "Živinice",
+ id: "ivinice",
+ olxid: "5774"
+ }
+ ]
+ },
+ {
+ name: " Zeničko-dobojski",
+ id: "zenickodobojski",
+ olxid: "4",
+ municipalities: [
+ {
+ name: "Breza",
+ id: "breza",
+ olxid: "704"
+ },
+ {
+ name: "Doboj-Jug",
+ id: "dobojjug",
+ olxid: "1122"
+ },
+ {
+ name: "Kakanj",
+ id: "kakanj",
+ olxid: "2022"
+ },
+ {
+ name: "Maglaj",
+ id: "maglaj",
+ olxid: "2941"
+ },
+ {
+ name: "Olovo",
+ id: "olovo",
+ olxid: "1925"
+ },
+ {
+ name: "Tešanj",
+ id: "teanj",
+ olxid: "4594"
+ },
+ {
+ name: "Usora",
+ id: "usora",
+ olxid: "1087"
+ },
+ {
+ name: "Vareš",
+ id: "vare",
+ olxid: "5037"
+ },
+ {
+ name: "Visoko",
+ id: "visoko",
+ olxid: "5171"
+ },
+ {
+ name: "Zavidovići",
+ id: "zavidovii",
+ olxid: "5548"
+ },
+ {
+ name: "Zenica",
+ id: "zenica",
+ olxid: "4571"
+ },
+ {
+ name: "Žepče",
+ id: "epe",
+ olxid: "2940"
+ }
+ ]
+ },
+ {
+ name: " Bosansko-podrinjski",
+ id: "bosanskopodrinjski",
+ olxid: "5",
+ municipalities: [
+ {
+ name: "Foča",
+ id: "foa",
+ olxid: "1289"
+ },
+ {
+ name: "Goražde",
+ id: "gorade",
+ olxid: "1588"
+ },
+ {
+ name: "Pale",
+ id: "pale",
+ olxid: "3546"
+ }
+ ]
+ },
+ {
+ name: " Srednjobosanski",
+ id: "srednjobosanski",
+ olxid: "6",
+ municipalities: [
+ {
+ name: "Bugojno",
+ id: "bugojno",
+ olxid: "732"
+ },
+ {
+ name: "Busovača",
+ id: "busovaa",
+ olxid: "810"
+ },
+ {
+ name: "Dobretići",
+ id: "dobretii",
+ olxid: "4151"
+ },
+ {
+ name: "Donji Vakuf",
+ id: "donjivakuf",
+ olxid: "1160"
+ },
+ {
+ name: "Fojnica",
+ id: "fojnica",
+ olxid: "1407"
+ },
+ {
+ name: "Gornji Vakuf - Uskoplje",
+ id: "gornjivakufuskoplje",
+ olxid: "1775"
+ },
+ {
+ name: "Jajce",
+ id: "jajce",
+ olxid: "1960"
+ },
+ {
+ name: "Kiseljak",
+ id: "kiseljak",
+ olxid: "2237"
+ },
+ {
+ name: "Kreševo",
+ id: "kreevo",
+ olxid: "2608"
+ },
+ {
+ name: "Novi Travnik",
+ id: "novitravnik",
+ olxid: "3477"
+ },
+ {
+ name: "Travnik",
+ id: "travnik",
+ olxid: "4678"
+ },
+ {
+ name: "Vitez",
+ id: "vitez",
+ olxid: "5422"
+ }
+ ]
+ },
+ {
+ name: " Hercegovačko-neretvanski",
+ id: "hercegovackoneretvanski",
+ olxid: "7",
+ municipalities: [
+ {
+ name: "Grad Mostar",
+ id: "gradmostar",
+ olxid: "3017"
+ },
+ {
+ name: "Jablanica",
+ id: "jablanica",
+ olxid: "1930"
+ },
+ {
+ name: "Konjic",
+ id: "konjic",
+ olxid: "2169"
+ },
+ {
+ name: "Neum",
+ id: "neum",
+ olxid: "3111"
+ },
+ {
+ name: "Prozor",
+ id: "prozor",
+ olxid: "3421"
+ },
+ {
+ name: "Ravno",
+ id: "ravno",
+ olxid: "4769"
+ },
+ {
+ name: "Stolac",
+ id: "stolac",
+ olxid: "4439"
+ },
+ {
+ name: "Čapljina",
+ id: "apljina",
+ olxid: "947"
+ },
+ {
+ name: "Čitluk",
+ id: "itluk",
+ olxid: "1009"
+ }
+ ]
+ },
+ {
+ name: " Zapadno-hercegovački",
+ id: "zapadnohercegovacki",
+ olxid: "8",
+ municipalities: [
+ {
+ name: "Grude",
+ id: "grude",
+ olxid: "1892"
+ },
+ {
+ name: "Ljubuški",
+ id: "ljubuki",
+ olxid: "2905"
+ },
+ {
+ name: "Posušje",
+ id: "posuje",
+ olxid: "3268"
+ },
+ {
+ name: "Široki Brijeg",
+ id: "irokibrijeg",
+ olxid: "2708"
+ }
+ ]
+ },
+ {
+ name: " Livanjski",
+ id: "livanjski",
+ olxid: "10",
+ municipalities: [
+ {
+ name: "Bosansko Grahovo",
+ id: "bosanskograhovo",
+ olxid: "560"
+ },
+ {
+ name: "Drvar",
+ id: "drvar",
+ olxid: "4640"
+ },
+ {
+ name: "Glamoč",
+ id: "glamo",
+ olxid: "1533"
+ },
+ {
+ name: "Kupres",
+ id: "kupres",
+ olxid: "2635"
+ },
+ {
+ name: "Livno",
+ id: "livno",
+ olxid: "2741"
+ },
+ {
+ name: "Tomislavgrad",
+ id: "tomislavgrad",
+ olxid: "1228"
+ }
+ ]
+ },
+ {
+ name: " Banjalučka",
+ id: "banjalučka",
+ olxid: "14",
+ municipalities: [
+ {
+ name: "Banja Luka",
+ id: "banjaluka",
+ olxid: "21"
+ },
+ {
+ name: "Gradiška",
+ id: "gradika",
+ olxid: "305"
+ },
+ {
+ name: "Istočni Drvar",
+ id: "istonidrvar",
+ olxid: "4662"
+ },
+ {
+ name: "Jezero",
+ id: "jezero",
+ olxid: "1965"
+ },
+ {
+ name: "Kneževo",
+ id: "kneevo",
+ olxid: "4147"
+ },
+ {
+ name: "Kostajnica",
+ id: "kostajnica",
+ olxid: "6142"
+ },
+ {
+ name: "Kotor Varoš",
+ id: "kotorvaro",
+ olxid: "2574"
+ },
+ {
+ name: "Kozarska Dubica",
+ id: "kozarskadubica",
+ olxid: "244"
+ },
+ {
+ name: "Krupa na uni",
+ id: "krupanauni",
+ olxid: "382"
+ },
+ {
+ name: "Kupres ",
+ id: "kupres",
+ olxid: "2654"
+ },
+ {
+ name: "Laktaši",
+ id: "laktai",
+ olxid: "2671"
+ },
+ {
+ name: "Mrkonjić Grad",
+ id: "mrkonjigrad",
+ olxid: "3073"
+ },
+ {
+ name: "Novi Grad",
+ id: "novigrad",
+ olxid: "444"
+ },
+ {
+ name: "Oštra Luka",
+ id: "otraluka",
+ olxid: "3737"
+ },
+ {
+ name: "Petrovac",
+ id: "petrovac",
+ olxid: "515"
+ },
+ {
+ name: "Prijedor",
+ id: "prijedor",
+ olxid: "3287"
+ },
+ {
+ name: "Prnjavor",
+ id: "prnjavor",
+ olxid: "3358"
+ },
+ {
+ name: "Ribnik",
+ id: "ribnik",
+ olxid: "2365"
+ },
+ {
+ name: "Srbac",
+ id: "srbac",
+ olxid: "4271"
+ },
+ {
+ name: "Čelinac",
+ id: "elinac",
+ olxid: "979"
+ },
+ {
+ name: "Šipovo",
+ id: "ipovo",
+ olxid: "4509"
+ }
+ ]
+ },
+ {
+ name: " Dobojsko-Bijeljinska",
+ id: "dobojskobijeljinska",
+ olxid: "15",
+ municipalities: [
+ {
+ name: "Bijeljina",
+ id: "bijeljina",
+ olxid: "123"
+ },
+ {
+ name: "Bosanski Brod",
+ id: "bosanskibrod",
+ olxid: "421"
+ },
+ {
+ name: "Derventa",
+ id: "derventa",
+ olxid: "1030"
+ },
+ {
+ name: "Doboj",
+ id: "doboj",
+ olxid: "1088"
+ },
+ {
+ name: "Donji Žabar",
+ id: "donjiabar",
+ olxid: "3254"
+ },
+ {
+ name: "Lopare",
+ id: "lopare",
+ olxid: "2800"
+ },
+ {
+ name: "Lukavac",
+ id: "lukavac",
+ olxid: "6029"
+ },
+ {
+ name: "Modriča",
+ id: "modria",
+ olxid: "2996"
+ },
+ {
+ name: "Pelagićevo",
+ id: "pelagievo",
+ olxid: "1856"
+ },
+ {
+ name: "Petrovo",
+ id: "petrovo",
+ olxid: "1827"
+ },
+ {
+ name: "Stanari",
+ id: "stanari",
+ olxid: "1148"
+ },
+ {
+ name: "Teslić",
+ id: "tesli",
+ olxid: "4549"
+ },
+ {
+ name: "Tešanj",
+ id: "teanj",
+ olxid: "4636"
+ },
+ {
+ name: "Travnik",
+ id: "travnik",
+ olxid: "4692"
+ },
+ {
+ name: "Tuzla",
+ id: "tuzla",
+ olxid: "4966"
+ },
+ {
+ name: "Ugljevik",
+ id: "ugljevik",
+ olxid: "5009"
+ },
+ {
+ name: "Vukosavlje",
+ id: "vukosavlje",
+ olxid: "3197"
+ },
+ {
+ name: "Šamac",
+ id: "amac",
+ olxid: "539"
+ }
+ ]
+ },
+ {
+ name: " Sarajevsko-Zvornička",
+ id: "sarajevskozvornicka",
+ olxid: "16",
+ municipalities: [
+ {
+ name: "Bratunac",
+ id: "bratunac",
+ olxid: "595"
+ },
+ {
+ name: "Han Pijesak",
+ id: "hanpijesak",
+ olxid: "1904"
+ },
+ {
+ name: "Ilijaš",
+ id: "ilija",
+ olxid: "3947"
+ },
+ {
+ name: "Istočni Stari Grad",
+ id: "istonistarigrad",
+ olxid: "4049"
+ },
+ {
+ name: "Kasindo",
+ id: "kasindo",
+ olxid: "3880"
+ },
+ {
+ name: "Kladanj",
+ id: "kladanj",
+ olxid: "2325"
+ },
+ {
+ name: "Lukavica",
+ id: "lukavica",
+ olxid: "3971"
+ },
+ {
+ name: "Milići",
+ id: "milii",
+ olxid: "6143"
+ },
+ {
+ name: "Olovo",
+ id: "olovo",
+ olxid: "3221"
+ },
+ {
+ name: "Osmaci",
+ id: "osmaci",
+ olxid: "2128"
+ },
+ {
+ name: "Pale",
+ id: "pale",
+ olxid: "3978"
+ },
+ {
+ name: "Rogatica",
+ id: "rogatica",
+ olxid: "3529"
+ },
+ {
+ name: "Rudo",
+ id: "rudo",
+ olxid: "3648"
+ },
+ {
+ name: "Sarajevo-Novi Grad",
+ id: "sarajevonovigrad",
+ olxid: "6069"
+ },
+ {
+ name: "Sokolac",
+ id: "sokolac",
+ olxid: "4183"
+ },
+ {
+ name: "Srebrenica",
+ id: "srebrenica",
+ olxid: "4310"
+ },
+ {
+ name: "Trnovo",
+ id: "trnovo",
+ olxid: "4067"
+ },
+ {
+ name: "Ustiprača",
+ id: "ustipraa",
+ olxid: "1593"
+ },
+ {
+ name: "Višegrad",
+ id: "viegrad",
+ olxid: "5259"
+ },
+ {
+ name: "Vlasenica",
+ id: "vlasenica",
+ olxid: "5456"
+ },
+ {
+ name: "Zvornik",
+ id: "zvornik",
+ olxid: "5684"
+ },
+ {
+ name: "Šekovići",
+ id: "ekovii",
+ olxid: "4475"
+ },
+ {
+ name: "Žepa",
+ id: "epa",
+ olxid: "1906"
+ }
+ ]
+ },
+ {
+ name: " Trebinjsko-Fočanska",
+ id: "trebinjskofocanska",
+ olxid: "17",
+ municipalities: [
+ {
+ name: "Berkovići",
+ id: "berkovii",
+ olxid: "4441"
+ },
+ {
+ name: "Bileća",
+ id: "bilea",
+ olxid: "183"
+ },
+ {
+ name: "Foča",
+ id: "foa",
+ olxid: "1287"
+ },
+ {
+ name: "Gacko",
+ id: "gacko",
+ olxid: "1462"
+ },
+ {
+ name: "Istočni Mostar",
+ id: "istonimostar",
+ olxid: "3038"
+ },
+ {
+ name: "Kalinovik",
+ id: "kalinovik",
+ olxid: "2164"
+ },
+ {
+ name: "Ljubinje",
+ id: "ljubinje",
+ olxid: "2884"
+ },
+ {
+ name: "Nevesinje",
+ id: "nevesinje",
+ olxid: "3138"
+ },
+ {
+ name: "Trebinje",
+ id: "trebinje",
+ olxid: "4766"
+ },
+ {
+ name: "Čajniče",
+ id: "ajnie",
+ olxid: "911"
+ }
+ ]
+ },
+ {
+ name: "Distrikt Brčko",
+ id: "distriktbrcko",
+ olxid: "12",
+ municipalities: [
+ {
+ name: "Brčko",
+ id: "brko",
+ olxid: "645"
+ }
+ ]
+ }
];
const getRegions = () => {
- return regions.map((g) => ({ name: g.name, id: g.id, olxid: g.olxid }));
+ return regions.map(g => ({ name: g.name, id: g.id, olxid: g.olxid }));
};
-const getRegion = (regionId) => {
- return regions.find(region => region.id === regionId);
+const getRegion = regionId => {
+ return regions.find(region => region.id === regionId);
};
-const getRegionName = (regionId) => {
- const region = getRegion(regionId);
- return (region && region.name) ? region.name : null;
+const getRegionName = regionId => {
+ const region = getRegion(regionId);
+ return region && region.name ? region.name : null;
};
-const getMunicipalitiesForRegion = (regionId) => {
- const region = getRegion(regionId);
- return (region && region.municipalities) ? region.municipalities : null;
+const getMunicipalitiesForRegion = regionId => {
+ const region = getRegion(regionId);
+ return region && region.municipalities ? region.municipalities : null;
};
const getMunicipality = (regionId, municipalityId) => {
- const region = getRegion(regionId);
- if (!region) {
- return null;
- }
+ const region = getRegion(regionId);
+ if (!region) {
+ return null;
+ }
- const municipality = region.municipalities.find(municipality => municipality.id === municipalityId);
- if (!municipality) {
- return null;
- }
+ const municipality = region.municipalities.find(
+ municipality => municipality.id === municipalityId
+ );
+ if (!municipality) {
+ return null;
+ }
- return municipality;
+ return municipality;
};
const getMunicipalityName = (regionId, municipalityId) => {
- const region = getRegion(regionId);
- if (!region) {
- return null;
- }
+ const region = getRegion(regionId);
+ if (!region) {
+ return null;
+ }
- const municipality = region.municipalities.find(municipality => municipality.id === municipalityId);
- if (!municipality) {
- return null;
- }
+ const municipality = region.municipalities.find(
+ municipality => municipality.id === municipalityId
+ );
+ if (!municipality) {
+ return null;
+ }
- return municipality.name;
+ return municipality.name;
};
module.exports = {
- getRegion,
- getRegions,
- getRegionName,
- getMunicipalitiesForRegion,
- getMunicipalityName,
- getMunicipality
+ getRegion,
+ getRegions,
+ getRegionName,
+ getMunicipalitiesForRegion,
+ getMunicipalityName,
+ getMunicipality
};
diff --git a/app/helpers/crawlers/olxClawler.js b/app/helpers/crawlers/olxClawler.js
index 139b30b..90e1543 100644
--- a/app/helpers/crawlers/olxClawler.js
+++ b/app/helpers/crawlers/olxClawler.js
@@ -1,375 +1,364 @@
-const fetch = require('node-fetch');
-const cheerio = require('cheerio');
-const { allRERequest, findPointInsideBoundingBox } = require('../db/dbHelper');
-const { getRealEstateTypeEnum } = require('../enums');
-const { getRegion, getMunicipality } = require('../codes')
+const fetch = require("node-fetch");
+const cheerio = require("cheerio");
+const { allRERequest, findPointInsideBoundingBox } = require("../db/dbHelper");
+const { getRealEstateTypeEnum } = require("../enums");
+const { getRegion, getMunicipality } = require("../codes");
const Promise = require("bluebird");
module.exports = class OlxCrawler {
- //TODO figure best way to handle paging
- constructor(hrefs = []) {
- this.hrefs = hrefs;
- }
+ //TODO figure best way to handle paging
+ constructor(hrefs = []) {
+ this.hrefs = hrefs;
+ }
- async indexPages(urls) {
- const indexers = [];
+ async indexPages(urls) {
+ const indexers = [];
- urls.forEach(url => {
- indexers.push(new Indexer(url));
- });
+ urls.forEach(url => {
+ indexers.push(new Indexer(url));
+ });
- return Promise.map(indexers, function (indexer) {
- return indexer.indexWithPagination();
- }).then(async (results) => {
- return results
- })
- }
+ return Promise.map(indexers, function(indexer) {
+ return indexer.indexWithPagination();
+ }).then(async results => {
+ return results;
+ });
+ }
- async crawl() {
- console.log("OLX CRAWLER: start crawl");
+ async crawl() {
+ const filteredResults = [];
+ const realestateRequests = await allRERequest();
+ const urls = this.createRequestUrls(realestateRequests);
+ let results = await this.indexPages(
+ urls,
+ this.fromPage,
+ this.toPage,
+ this.maxResults
+ );
+ const flatResults = results.flat();
+ if (flatResults) {
+ for (const finalResult of flatResults) {
+ if (null !== finalResult) {
+ if (
+ finalResult.lat !== undefined &&
+ finalResult.lat !== null &&
+ finalResult.lat !== ""
+ ) {
+ const pointInsideBoundingBox = await findPointInsideBoundingBox(
+ [finalResult.lng, finalResult.lat],
+ finalResult.email,
+ finalResult.uuid
+ );
- const filteredResults = [];
- const realestateRequests = await allRERequest();
- console.log("OLX CRAWLER: found " + realestateRequests.length + "subscribed RealEstateRequests");
- const urls = this.createRequestUrls(realestateRequests);
- let results = await this.indexPages(urls, this.fromPage, this.toPage, this.maxResults);
- console.log("Final crawler results");
- const flatResults = results.flat();
- console.log(flatResults);
- if (flatResults) {
- console.log(flatResults.length);
-
- for (const finalResult of flatResults) {
-
- if (null !== finalResult) {
- if (finalResult.lat !== undefined && finalResult.lat !== null && finalResult.lat !== "") {
- const pointInsideBoundingBox = await findPointInsideBoundingBox([finalResult.lng, finalResult.lat], finalResult.email, finalResult.uuid);
-
-
- if (pointInsideBoundingBox[0].length !== 0) {
- finalResult.hasLocation = true
- filteredResults.push(finalResult);
- } else {
- finalResult.hasLocation = false
- filteredResults.push(finalResult);
- }
- }
- }
+ if (pointInsideBoundingBox[0].length !== 0) {
+ finalResult.hasLocation = true;
+ filteredResults.push(finalResult);
+ } else {
+ finalResult.hasLocation = false;
+ filteredResults.push(finalResult);
}
-
- console.log("OLX CRAWLER: number of olx crawler results, after geo location filtering: " + filteredResults.length);
- return filteredResults;
+ }
}
- return []
+ }
+ return filteredResults;
+ }
+ return [];
+ }
+
+ createRequestUrls(realestateRequests) {
+ const urls = [];
+
+ for (const request of realestateRequests) {
+ const realsestateType =
+ "kategorija=" +
+ getRealEstateTypeEnum(request.realEstateType).olxCategory;
+ const region = "kanton=" + getRegion(request.region).olxid;
+ const municipality =
+ "grad%5B%5D=" +
+ getMunicipality(request.region, request.municipality).olxid;
+ const sizeMin = "kvadrata_min=" + request.sizeMin;
+ const sizeMax = "kvadrata_max=" + request.sizeMax;
+ const priceMin = "od=" + request.priceMin;
+ const priceMax = "do=" + request.priceMax;
+
+ const olxUrl = {
+ url: `https://www.olx.ba/pretraga?${realsestateType}&id=2&stanje=0&vrstapregleda=tabela&sort_order=desc&${region}&${municipality}&${priceMin}&${priceMax}&vrsta=samoprodaja&${sizeMin}&${sizeMax}&stranica=`,
+ email: request.email,
+ uuid: request.uniqueId,
+ hrefs: this.hrefs
+ };
+ urls.push(olxUrl);
}
- createRequestUrls(realestateRequests) {
- const urls = []
-
- for (const request of realestateRequests) {
- const realsestateType = "kategorija=" + getRealEstateTypeEnum(request.realEstateType).olxCategory;
- const region = "kanton=" + getRegion(request.region).olxid;
- const municipality = "grad%5B%5D=" + getMunicipality(request.region, request.municipality).olxid;
- const sizeMin = "kvadrata_min=" + request.sizeMin;
- const sizeMax = "kvadrata_max=" + request.sizeMax;
- const priceMin = "od=" + request.priceMin;
- const priceMax = "do=" + request.priceMax;
-
- const olxUrl = {
- url: `https://www.olx.ba/pretraga?${realsestateType}&id=2&stanje=0&vrstapregleda=tabela&sort_order=desc&${region}&${municipality}&${priceMin}&${priceMax}&vrsta=samoprodaja&${sizeMin}&${sizeMax}&stranica=`,
- email: request.email,
- uuid: request.uniqueId,
- hrefs: this.hrefs
- }
- console.log(olxUrl.url);
- urls.push(olxUrl);
- }
-
- return urls;
- }
+ return urls;
+ }
};
-
class Indexer {
+ /**
+ *
+ * @param {String|Array} olxUrl single or array of objects containing url email and uuid
+ * @param {Array} hrefResutls array contaning urls from crawler results
+ */
- /**
- *
- * @param {String|Array} olxUrl single or array of objects containing url email and uuid
- * @param {Array} hrefResutls array contaning urls from crawler results
- */
+ constructor(olxUrl, hrefResutls) {
+ this.olxUrl = olxUrl;
+ this.hrefResutls = hrefResutls;
+ }
- constructor(olxUrl, hrefResutls) {
- this.olxUrl = olxUrl;
- this.hrefResutls = hrefResutls;
- }
+ async indexWithPagination(pageNumber = 1) {
+ const pageNr = this.olxUrl.url.match(/\d+$/);
+ const indexers = this.prepareIndexers(pageNumber ? [pageNumber] : pageNr);
- async indexWithPagination(pageNumber = 1) {
+ try {
+ return Promise.map(indexers.indexers, function(indexer) {
+ return indexer.indexPage(pageNumber);
+ }).then(async results => {
+ let hasResults = false;
- console.log("This is olxUrl:" + this.olxUrl.url);
- const pageNr = this.olxUrl.url.match(/\d+$/);
- const indexers = this.prepareIndexers(pageNumber ? [pageNumber] : pageNr);
+ results.forEach(result => {
+ if (!hasResults) {
+ hasResults = result.hasResults;
+ }
+ });
- try {
+ if (!hasResults) {
+ const singlePageIndexers = this.prepareHrefIndexers(results);
+ if (singlePageIndexers.length === 0) {
+ return [];
+ }
- return Promise.map(indexers.indexers, function (indexer) {
- return indexer.indexPage(pageNumber);
- }).then(async (results) => {
- let hasResults = false;
-
- results.forEach(result => {
- if (!hasResults) {
- console.log("No results detected")
- hasResults = result.hasResults
- }
- });
-
- if (!hasResults) {
- console.log("HAS NO MORE RESULTS, stop the paging, there are some results and they should contain only HREFS");
- console.log(results.length);
- const singlePageIndexers = this.prepareHrefIndexers(results);
- if (singlePageIndexers.length === 0) {
- console.log("THERE IS NOT EVEN SINGLE RESULT");
- return []
- }
-
- return Promise.map(singlePageIndexers, function (indexer) {
- return indexer.indexSingle();
- }).then(async (results) => {
- console.log("SinglePageMethod in HAS NO RESULTS, MarketAralms");
- console.log(results.length);
- return results;
- });
-
- } else {
- console.log("HAS MORE RESULTS, should only contain HREFS");
- console.log(results.length);
- const newResults = await this.indexWithPagination(results[0].pageNumber + 5);
- const singlePageIndexers = this.prepareHrefIndexers(results);
-
- const newerResults = await Promise.map(singlePageIndexers, function (indexer) {
- return indexer.indexSingle();
- }).then(async (results) => {
- console.log("SinglePageMethod HAS RESULTS, should contain MarketAlerts only");
- console.log(results.length);
- return results;
- });
-
- Array.prototype.push.apply(newResults, newerResults);
- return newResults;
-
- }
- });
- } catch (e) {
- console.error("Error has accured", e);
- }
-
- }
-
- prepareIndexers(pageNr) {
-
- console.log("Entering prepareIndexers : page nr - " + pageNr);
- const indexers = [];
- let lastPageNumber;
- if (pageNr) {
- for (let index = Number(pageNr[0]); index <= Number(pageNr[0]) + 5; index++) {
- lastPageNumber = index;
- const newOlxUrl = {
- url: this.olxUrl.url.replace(/\d+$/, "") + index,
- email: this.olxUrl.email,
- uuid: this.olxUrl.uuid,
- hrefs: this.olxUrl.hrefs
- }
- indexers.push(new Indexer(newOlxUrl));
-
- }
+ return Promise.map(singlePageIndexers, function(indexer) {
+ return indexer.indexSingle();
+ }).then(async results => {
+ return results;
+ });
} else {
- for (let index = 1; index <= 5; index++) {
- lastPageNumber = index;
- const newOlxUrl = {
- url: this.olxUrl.url + index,
- email: this.olxUrl.email,
- uuid: this.olxUrl.uuid,
- hrefs: this.olxUrl.hrefs
- }
- indexers.push(new Indexer(newOlxUrl));
- }
+ const newResults = await this.indexWithPagination(
+ results[0].pageNumber + 5
+ );
+ const singlePageIndexers = this.prepareHrefIndexers(results);
+
+ const newerResults = await Promise.map(singlePageIndexers, function(
+ indexer
+ ) {
+ return indexer.indexSingle();
+ }).then(async results => {
+ return results;
+ });
+
+ Array.prototype.push.apply(newResults, newerResults);
+ return newResults;
}
- return {
- indexers: indexers,
- lastPageNumber: lastPageNumber
+ });
+ } catch (e) {
+ console.error("Error has accured", e);
+ }
+ }
+
+ prepareIndexers(pageNr) {
+ const indexers = [];
+ let lastPageNumber;
+ if (pageNr) {
+ for (
+ let index = Number(pageNr[0]);
+ index <= Number(pageNr[0]) + 5;
+ index++
+ ) {
+ lastPageNumber = index;
+ const newOlxUrl = {
+ url: this.olxUrl.url.replace(/\d+$/, "") + index,
+ email: this.olxUrl.email,
+ uuid: this.olxUrl.uuid,
+ hrefs: this.olxUrl.hrefs
};
+ indexers.push(new Indexer(newOlxUrl));
+ }
+ } else {
+ for (let index = 1; index <= 5; index++) {
+ lastPageNumber = index;
+ const newOlxUrl = {
+ url: this.olxUrl.url + index,
+ email: this.olxUrl.email,
+ uuid: this.olxUrl.uuid,
+ hrefs: this.olxUrl.hrefs
+ };
+ indexers.push(new Indexer(newOlxUrl));
+ }
}
+ return {
+ indexers: indexers,
+ lastPageNumber: lastPageNumber
+ };
+ }
- prepareHrefIndexers(results) {
- const indexers = []
+ prepareHrefIndexers(results) {
+ const indexers = [];
- if (!Array.isArray(results)) {
- results.hrefs.forEach(href => {
- const newOlxUrl = {
- url: href,
- email: results.olxUrl.email,
- uuid: results.olxUrl.uuid,
- hrefs: this.olxUrl.hrefs
- }
+ if (!Array.isArray(results)) {
+ results.hrefs.forEach(href => {
+ const newOlxUrl = {
+ url: href,
+ email: results.olxUrl.email,
+ uuid: results.olxUrl.uuid,
+ hrefs: this.olxUrl.hrefs
+ };
- indexers.push(new Indexer(newOlxUrl));
- });
-
- } else {
-
-
- results.forEach(result => {
-
- if (result !== null && result.hasOwnProperty('hrefs')) {
- result.hrefs.forEach(href => {
- const newOlxUrl = {
- url: href,
- email: result.olxUrl.email,
- uuid: result.olxUrl.uuid,
- hrefs: this.olxUrl.hrefs
- }
-
- indexers.push(new Indexer(newOlxUrl));
- })
- }
-
- });
- }
-
- return indexers;
- }
-
- async indexPage(pageNumber) {
- console.log("Page number in index page, max page number :")
- console.log(pageNumber);
-
- try {
-
- console.log("Indexing page: " + this.olxUrl.url);
- const res = await fetch(this.olxUrl.url);
- const body = await res.text();
- const $ = cheerio.load(body);
- const hrefs = [];
- let hasResults = false
-
- $('#rezultatipretrage').find('.listitem').each((i, elem) => {
- hasResults = true
- const href = $(elem).find('a').first().attr('href');
- hrefs.push(href);
- });
-
- console.log("this is hrefs for olxUrl" + this.olxUrl.url);
- console.log("NUMBER OF HREFS " + hrefs.length);
-
- return {
- hrefs: hrefs,
- hasResults: hasResults,
- pageNumber: pageNumber,
- olxUrl: this.olxUrl
- }
- } catch (e) {
- console.error('Exception caught:' + e);
- }
- }
-
- async indexSingle() {
- try {
- console.log("Index single");
- console.log(this.olxUrl.url);
-
- if (this.olxUrl.url === undefined) {
- return {}
- }
-
- // if (global.hrefs) {
-
- if (this.olxUrl.hrefs[this.olxUrl.uuid] && this.olxUrl.hrefs[this.olxUrl.uuid].includes(this.olxUrl.url)) {
-
- console.log("We found duplicate URL");
- return null
- }
- // }
-
- const res = await fetch(this.olxUrl.url);
- const body = await res.text();
- const $ = cheerio.load(body);
-
- const title = $('#naslovartikla').text().trim();
- const realEstateType = $('#artikal_glavni_div > div.artikal_lijevo > div:nth-child(3) > div > span:nth-child(3) > a > span').text();
-
- const price = $('#pc > p:nth-child(2)').text();
- const size = $('#dodatnapolja1 > div:nth-child(1) > div.df2').text();
- const rooms = $('#dodatnapolja1 > div:nth-child(2) > div.df2').text();
- const address = $('#dodatnapolja1 > div:nth-child(5) > div.df2').text();
- const gardenSize = $('#dodatnapolja1 > div:nth-child(6) > div.df2').text();
- const location = $('#artikal_glavni_div > div.artikal_lijevo > div.op.pop.mobile-lokacija').attr('data-content');
-
- const time = $('time').attr('datetime');
- const olxId = $('#artikal_glavni_div > div.artikal_lijevo > div:nth-child(15) > div:nth-child(4) > div.df2').text();
-
- const descriptions = $('.artikal_detaljniopis_tekst');
- const latLngRe = /LatLng\(([0-9]+\.[0-9]+)\,\s+([0-9]+\.[0-9]+)\)/g;
- const imgRe = /href":("[^"]*")/g;
- const matches = latLngRe.exec(body);
- let lng = '',
- lat = '';
- const parsePrice = (price) => parseFloat(price.replace(".", ""))
-
- if (matches && matches.length >= 3) {
- lat = matches[1];
- lng = matches[2];
- }
-
- const parsedPrice = parsePrice(price);
-
- const locationArray = location.split(",");
- const region = locationArray[0];
- const municipality = locationArray[1];
-
- const data = {
- realEstateType: this.getCategoryId(realEstateType),
- email: this.olxUrl.email,
- uuid: this.olxUrl.uuid,
- olxId: olxId,
- url: this.olxUrl.url,
- title,
- price: isNaN(parsedPrice) ? 0 : parsedPrice,
- size: parseFloat(size),
- gardenSize: isNaN(parseFloat(gardenSize)) ? 0 : parseFloat(gardenSize),
- address,
- region,
- municipality,
- time,
- shortDescription: descriptions.first().text(),
- longDescription: descriptions.last().text(),
- lat,
- lng,
- loc: [parseFloat(lat), parseFloat(lng)],
+ indexers.push(new Indexer(newOlxUrl));
+ });
+ } else {
+ results.forEach(result => {
+ if (result !== null && result.hasOwnProperty("hrefs")) {
+ result.hrefs.forEach(href => {
+ const newOlxUrl = {
+ url: href,
+ email: result.olxUrl.email,
+ uuid: result.olxUrl.uuid,
+ hrefs: this.olxUrl.hrefs
};
- return data;
- } catch (e) {
- console.error('Exception caught: ' + e.message);
+ indexers.push(new Indexer(newOlxUrl));
+ });
}
+ });
+ }
+ return indexers;
+ }
+
+ async indexPage(pageNumber) {
+ try {
+ const res = await fetch(this.olxUrl.url);
+ const body = await res.text();
+ const $ = cheerio.load(body);
+ const hrefs = [];
+ let hasResults = false;
+
+ $("#rezultatipretrage")
+ .find(".listitem")
+ .each((i, elem) => {
+ hasResults = true;
+ const href = $(elem)
+ .find("a")
+ .first()
+ .attr("href");
+ hrefs.push(href);
+ });
+ return {
+ hrefs: hrefs,
+ hasResults: hasResults,
+ pageNumber: pageNumber,
+ olxUrl: this.olxUrl
+ };
+ } catch (e) {
+ console.error("Exception caught:" + e);
+ }
+ }
+
+ async indexSingle() {
+ try {
+ if (this.olxUrl.url === undefined) {
+ return {};
+ }
+
+ // if (global.hrefs) {
+
+ if (
+ this.olxUrl.hrefs[this.olxUrl.uuid] &&
+ this.olxUrl.hrefs[this.olxUrl.uuid].includes(this.olxUrl.url)
+ ) {
return null;
+ }
+ // }
+
+ const res = await fetch(this.olxUrl.url);
+ const body = await res.text();
+ const $ = cheerio.load(body);
+
+ const title = $("#naslovartikla")
+ .text()
+ .trim();
+ const realEstateType = $(
+ "#artikal_glavni_div > div.artikal_lijevo > div:nth-child(3) > div > span:nth-child(3) > a > span"
+ ).text();
+
+ const price = $("#pc > p:nth-child(2)").text();
+ const size = $("#dodatnapolja1 > div:nth-child(1) > div.df2").text();
+ const rooms = $("#dodatnapolja1 > div:nth-child(2) > div.df2").text();
+ const address = $("#dodatnapolja1 > div:nth-child(5) > div.df2").text();
+ const gardenSize = $(
+ "#dodatnapolja1 > div:nth-child(6) > div.df2"
+ ).text();
+ const location = $(
+ "#artikal_glavni_div > div.artikal_lijevo > div.op.pop.mobile-lokacija"
+ ).attr("data-content");
+
+ const time = $("time").attr("datetime");
+ const olxId = $(
+ "#artikal_glavni_div > div.artikal_lijevo > div:nth-child(15) > div:nth-child(4) > div.df2"
+ ).text();
+
+ const descriptions = $(".artikal_detaljniopis_tekst");
+ const latLngRe = /LatLng\(([0-9]+\.[0-9]+)\,\s+([0-9]+\.[0-9]+)\)/g;
+ const imgRe = /href":("[^"]*")/g;
+ const matches = latLngRe.exec(body);
+ let lng = "",
+ lat = "";
+ const parsePrice = price => parseFloat(price.replace(".", ""));
+
+ if (matches && matches.length >= 3) {
+ lat = matches[1];
+ lng = matches[2];
+ }
+
+ const parsedPrice = parsePrice(price);
+
+ const locationArray = location.split(",");
+ const region = locationArray[0];
+ const municipality = locationArray[1];
+
+ const data = {
+ realEstateType: this.getCategoryId(realEstateType),
+ email: this.olxUrl.email,
+ uuid: this.olxUrl.uuid,
+ olxId: olxId,
+ url: this.olxUrl.url,
+ title,
+ price: isNaN(parsedPrice) ? 0 : parsedPrice,
+ size: parseFloat(size),
+ gardenSize: isNaN(parseFloat(gardenSize)) ? 0 : parseFloat(gardenSize),
+ address,
+ region,
+ municipality,
+ time,
+ shortDescription: descriptions.first().text(),
+ longDescription: descriptions.last().text(),
+ lat,
+ lng,
+ loc: [parseFloat(lat), parseFloat(lng)]
+ };
+
+ return data;
+ } catch (e) {
+ console.error("Exception caught: " + e.message);
}
- getCategoryId(category) {
+ return null;
+ }
- switch (category) {
- case 'Stanovi':
- return 'stan';
+ getCategoryId(category) {
+ switch (category) {
+ case "Stanovi":
+ return "stan";
- case 'Vikendice':
- return 'vikendica'
+ case "Vikendice":
+ return "vikendica";
- case 'Kuće':
- return 'kuca';
+ case "Kuće":
+ return "kuca";
- default:
- return '';
- }
+ default:
+ return "";
}
+ }
}
-
diff --git a/app/helpers/email.js b/app/helpers/email.js
index c5b7d66..730f2a6 100644
--- a/app/helpers/email.js
+++ b/app/helpers/email.js
@@ -1,7 +1,6 @@
-
-const isValidEmail = (email) => {
+const isValidEmail = email => {
const simpleEmailRegex = /^.+@.+\..+$/;
- return (email && email.length < 250 && simpleEmailRegex.test(email));
+ return email && email.length < 250 && simpleEmailRegex.test(email);
};
module.exports = {
diff --git a/app/helpers/enums.js b/app/helpers/enums.js
index ff78e09..91c243d 100644
--- a/app/helpers/enums.js
+++ b/app/helpers/enums.js
@@ -1,57 +1,57 @@
const realEstateTypes = [
- { title: "Kuća", id: "kuca", hasGardenSize: true, olxCategory: 24 },
- { title: "Stan", id: "stan", hasGardenSize: false, olxCategory: 23},
- { title: "Vikendica", id: "vikendica", hasGardenSize: true, olxCategory: 26 }
+ { title: "Kuća", id: "kuca", hasGardenSize: true, olxCategory: 24 },
+ { title: "Stan", id: "stan", hasGardenSize: false, olxCategory: 23 },
+ { title: "Vikendica", id: "vikendica", hasGardenSize: true, olxCategory: 26 }
];
const sizes = [
- { title: "do 50 m2", id: "50m2" },
- { title: "do 75 m2", id: "75m2" },
- { title: "do 100 m2", id: "100m2" },
- { title: "do 150 m2", id: "150m2" },
- { title: "do 200 m2", id: "200m2" },
- { title: "preko 200 m2", id: "moreThan200m2" }
+ { title: "do 50 m2", id: "50m2" },
+ { title: "do 75 m2", id: "75m2" },
+ { title: "do 100 m2", id: "100m2" },
+ { title: "do 150 m2", id: "150m2" },
+ { title: "do 200 m2", id: "200m2" },
+ { title: "preko 200 m2", id: "moreThan200m2" }
];
const gardenSizes = [
- { title: "do 100 m2", id: "100m2" },
- { title: "do 500 m2", id: "500m2" },
- { title: "do 1 dunum", id: "1000m2" },
- { title: "do 2 dunuma", id: "2000m2" },
- { title: "do 3 dunuma", id: "3000m2" },
- { title: "preko 3 dunuma", id: "moreThan3000m2" }
+ { title: "do 100 m2", id: "100m2" },
+ { title: "do 500 m2", id: "500m2" },
+ { title: "do 1 dunum", id: "1000m2" },
+ { title: "do 2 dunuma", id: "2000m2" },
+ { title: "do 3 dunuma", id: "3000m2" },
+ { title: "preko 3 dunuma", id: "moreThan3000m2" }
];
const prices = [
- { title: "do 50 000 KM", id: "50kKM" },
- { title: "do 100 000 KM", id: "100kKM" },
- { title: "do 150 000 KM", id: "150kKM" },
- { title: "do 200 000 KM", id: "200kKM" },
- { title: "do 250 000 KM", id: "250kKM" },
- { title: "preko 250 000 KM", id: "moreThan250kKM" }
+ { title: "do 50 000 KM", id: "50kKM" },
+ { title: "do 100 000 KM", id: "100kKM" },
+ { title: "do 150 000 KM", id: "150kKM" },
+ { title: "do 200 000 KM", id: "200kKM" },
+ { title: "do 250 000 KM", id: "250kKM" },
+ { title: "preko 250 000 KM", id: "moreThan250kKM" }
];
const getEnumObject = (enumType, enumId) => {
- return enumType.find(enumValue => enumValue.id === enumId);
+ return enumType.find(enumValue => enumValue.id === enumId);
};
-const getRealEstateTypeEnum = (enumId) => {
- return getEnumObject(realEstateTypes, enumId) || null;
-}
+const getRealEstateTypeEnum = enumId => {
+ return getEnumObject(realEstateTypes, enumId) || null;
+};
const getEnumTypeTitle = (enumType, enumId) => {
- const enumObject = getEnumObject(enumType, enumId);
- if (!enumObject){
- return null;
- }
- return enumObject.title;
+ const enumObject = getEnumObject(enumType, enumId);
+ if (!enumObject) {
+ return null;
+ }
+ return enumObject.title;
};
module.exports = {
- realEstateTypes,
- sizes,
- gardenSizes,
- prices,
- getRealEstateTypeEnum,
- getEnumTypeTitle,
+ realEstateTypes,
+ sizes,
+ gardenSizes,
+ prices,
+ getRealEstateTypeEnum,
+ getEnumTypeTitle
};
diff --git a/app/helpers/url.js b/app/helpers/url.js
index 8bf1cb5..78036c5 100644
--- a/app/helpers/url.js
+++ b/app/helpers/url.js
@@ -1,12 +1,12 @@
-const db = require('../models/index');
+const db = require("../models/index");
-const currentRERequest = async (req) => {
- const uniqueId = req.params['request_id'];
- if(!uniqueId) return null;
+const currentRERequest = async req => {
+ const uniqueId = req.params["request_id"];
+ if (!uniqueId) return null;
- const request = await db.RealEstateRequest.findOne({ where: {uniqueId} });
+ const request = await db.RealEstateRequest.findOne({ where: { uniqueId } });
return request;
};
module.exports = {
- currentRERequest,
+ currentRERequest
};
diff --git a/app/lib/sendNotification.js b/app/lib/sendNotification.js
index fe84d31..14e6b73 100644
--- a/app/lib/sendNotification.js
+++ b/app/lib/sendNotification.js
@@ -1,9 +1,8 @@
const scrapTheItems = require("./scrapTheItems");
const convertToDate = require("./convertToDate");
-const AWS = require('aws-sdk');
+const AWS = require("aws-sdk");
// AWS.config.update({region: 'eu-central-1'});
-
async function sendNotification(marketAlert) {
const { id, email, olx_url } = marketAlert;
let url =
@@ -19,37 +18,37 @@ async function sendNotification(marketAlert) {
// Create sendEmail params
const params = {
- Destination: { /* required */
- CcAddresses: [
- ],
- ToAddresses: [
- email
- ]
+ Destination: {
+ /* required */
+ CcAddresses: [],
+ ToAddresses: [email]
},
- Message: { /* required */
- Body: { /* required */
+ Message: {
+ /* required */
+ Body: {
+ /* required */
Html: {
- Charset: "UTF-8",
- Data: message
+ Charset: "UTF-8",
+ Data: message
},
Text: {
- Charset: "UTF-8",
- Data: message // TODO: convert to text
+ Charset: "UTF-8",
+ Data: message // TODO: convert to text
}
- },
- Subject: {
- Charset: 'UTF-8',
- Data: 'Javimi alert'
- }
+ },
+ Subject: {
+ Charset: "UTF-8",
+ Data: "Javimi alert"
+ }
},
- Source: 'info@saburly.com', /* required */
- ReplyToAddresses: [
- 'info@saburly.com',
- ],
+ Source: "info@saburly.com" /* required */,
+ ReplyToAddresses: ["info@saburly.com"]
};
if (message) {
- const sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();
+ const sendPromise = new AWS.SES({ apiVersion: "2010-12-01" })
+ .sendEmail(params)
+ .promise();
await sendPromise;
return { id, date: String(convertToDate(lastDate)) };
}
diff --git a/app/migrations/20190417035319-create-market-alert.js b/app/migrations/20190417035319-create-market-alert.js
index 9ad4e62..7c4260f 100644
--- a/app/migrations/20190417035319-create-market-alert.js
+++ b/app/migrations/20190417035319-create-market-alert.js
@@ -1,7 +1,7 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.createTable('MarketAlerts', {
+ return queryInterface.createTable("MarketAlerts", {
id: {
allowNull: false,
autoIncrement: true,
@@ -29,6 +29,6 @@ module.exports = {
});
},
down: (queryInterface, Sequelize) => {
- return queryInterface.dropTable('MarketAlerts');
+ return queryInterface.dropTable("MarketAlerts");
}
};
diff --git a/app/migrations/20190417035707-create-real-estate-request.js b/app/migrations/20190417035707-create-real-estate-request.js
index 49be61f..b0309f9 100644
--- a/app/migrations/20190417035707-create-real-estate-request.js
+++ b/app/migrations/20190417035707-create-real-estate-request.js
@@ -1,7 +1,7 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.createTable('RealEstateRequests', {
+ return queryInterface.createTable("RealEstateRequests", {
id: {
allowNull: false,
autoIncrement: true,
@@ -28,6 +28,6 @@ module.exports = {
});
},
down: (queryInterface, Sequelize) => {
- return queryInterface.dropTable('RealEstateRequests');
+ return queryInterface.dropTable("RealEstateRequests");
}
};
diff --git a/app/migrations/20190427043621-add_city_to_real_estate_request.js b/app/migrations/20190427043621-add_city_to_real_estate_request.js
index be6f6a8..f64f12d 100644
--- a/app/migrations/20190427043621-add_city_to_real_estate_request.js
+++ b/app/migrations/20190427043621-add_city_to_real_estate_request.js
@@ -1,18 +1,15 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn(
- 'RealEstateRequests',
- 'city',
- Sequelize.STRING
+ "RealEstateRequests",
+ "city",
+ Sequelize.STRING
);
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'city'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "city");
}
};
diff --git a/app/migrations/20190429050222-add_place_to_real_estate_request.js b/app/migrations/20190429050222-add_place_to_real_estate_request.js
index 3fb0b4b..5273e5f 100644
--- a/app/migrations/20190429050222-add_place_to_real_estate_request.js
+++ b/app/migrations/20190429050222-add_place_to_real_estate_request.js
@@ -1,18 +1,15 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn(
- 'RealEstateRequests',
- 'place',
- Sequelize.STRING
+ "RealEstateRequests",
+ "place",
+ Sequelize.STRING
);
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'place'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "place");
}
};
diff --git a/app/migrations/20190516180226-rename-place-column.js b/app/migrations/20190516180226-rename-place-column.js
index 55f6484..58b9581 100644
--- a/app/migrations/20190516180226-rename-place-column.js
+++ b/app/migrations/20190516180226-rename-place-column.js
@@ -1,19 +1,19 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.renameColumn(
- 'RealEstateRequests',
- 'place',
- 'municipality'
+ "RealEstateRequests",
+ "place",
+ "municipality"
);
},
down: (queryInterface, Sequelize) => {
return queryInterface.renameColumn(
- 'RealEstateRequests',
- 'municipality',
- 'place'
+ "RealEstateRequests",
+ "municipality",
+ "place"
);
}
};
diff --git a/app/migrations/20190516222240-rename-city-column.js b/app/migrations/20190516222240-rename-city-column.js
index 7b8742e..2a0e717 100644
--- a/app/migrations/20190516222240-rename-city-column.js
+++ b/app/migrations/20190516222240-rename-city-column.js
@@ -1,19 +1,11 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.renameColumn(
- 'RealEstateRequests',
- 'city',
- 'region'
- );
+ return queryInterface.renameColumn("RealEstateRequests", "city", "region");
},
down: (queryInterface, Sequelize) => {
- return queryInterface.renameColumn(
- 'RealEstateRequests',
- 'region',
- 'city'
- );
+ return queryInterface.renameColumn("RealEstateRequests", "region", "city");
}
};
diff --git a/app/migrations/20190517072957-add-size-to-real-estate-request.js b/app/migrations/20190517072957-add-size-to-real-estate-request.js
index 7f28585..e910c21 100644
--- a/app/migrations/20190517072957-add-size-to-real-estate-request.js
+++ b/app/migrations/20190517072957-add-size-to-real-estate-request.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'RealEstateRequests',
- 'size',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("RealEstateRequests", "size", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'size'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "size");
}
};
diff --git a/app/migrations/20190517090015-add-gardenSize-to-real-estate-request.js b/app/migrations/20190517090015-add-gardenSize-to-real-estate-request.js
index 84e2319..18e7f4c 100644
--- a/app/migrations/20190517090015-add-gardenSize-to-real-estate-request.js
+++ b/app/migrations/20190517090015-add-gardenSize-to-real-estate-request.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'RealEstateRequests',
- 'gardenSize',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("RealEstateRequests", "gardenSize", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'gardenSize'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "gardenSize");
}
};
diff --git a/app/migrations/20190517092716-add-price-to-real-estate-request.js b/app/migrations/20190517092716-add-price-to-real-estate-request.js
index 13bcae6..2035378 100644
--- a/app/migrations/20190517092716-add-price-to-real-estate-request.js
+++ b/app/migrations/20190517092716-add-price-to-real-estate-request.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'RealEstateRequests',
- 'price',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("RealEstateRequests", "price", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'price'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "price");
}
};
diff --git a/app/migrations/20190523144812-activate-postgis.js b/app/migrations/20190523144812-activate-postgis.js
index 8b944e3..48c8cde 100644
--- a/app/migrations/20190523144812-activate-postgis.js
+++ b/app/migrations/20190523144812-activate-postgis.js
@@ -1,15 +1,19 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.query("CREATE EXTENSION postgis").then(([results, metadata]) => {
- /// No result
- })
+ return queryInterface.sequelize
+ .query("CREATE EXTENSION postgis")
+ .then(([results, metadata]) => {
+ /// No result
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.query("DROP EXTENSION IF EXISTS postgis").then(([results, metadata]) => {
+ return queryInterface.sequelize
+ .query("DROP EXTENSION IF EXISTS postgis")
+ .then(([results, metadata]) => {
/// No result
- })
+ });
}
};
diff --git a/app/migrations/20190523151420-add-bounding-box-column.js b/app/migrations/20190523151420-add-bounding-box-column.js
index e319421..601b566 100644
--- a/app/migrations/20190523151420-add-bounding-box-column.js
+++ b/app/migrations/20190523151420-add-bounding-box-column.js
@@ -1,17 +1,21 @@
-'use strict';
+"use strict";
module.exports = {
-
up: (queryInterface, Sequelize) => {
-
- return queryInterface.sequelize.query("ALTER TABLE \"RealEstateRequests\" ADD COLUMN bounding_box geometry(Polygon);").then(([results, metadata]) => {
- /// No result
- })
+ return queryInterface.sequelize
+ .query(
+ 'ALTER TABLE "RealEstateRequests" ADD COLUMN bounding_box geometry(Polygon);'
+ )
+ .then(([results, metadata]) => {
+ /// No result
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.query("ALTER TABLE \"RealEstateRequests\" DROP COLUMN bounding_box").then(([results, metadata]) => {
- /// No result
- })
+ return queryInterface.sequelize
+ .query('ALTER TABLE "RealEstateRequests" DROP COLUMN bounding_box')
+ .then(([results, metadata]) => {
+ /// No result
+ });
}
-};
\ No newline at end of file
+};
diff --git a/app/migrations/20190529093410-slider-fields.js b/app/migrations/20190529093410-slider-fields.js
index d260600..b4dc687 100644
--- a/app/migrations/20190529093410-slider-fields.js
+++ b/app/migrations/20190529093410-slider-fields.js
@@ -1,27 +1,48 @@
module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.addColumn('RealEstateRequests', 'sizeRange', {
- type: Sequelize.STRING
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'gardenSizeRange', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'priceRange', {
- type: Sequelize.STRING,
- }, { transaction: t })
- ])
- })
- },
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "sizeRange",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "gardenSizeRange",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "priceRange",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ },
- down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('RealEstateRequests', 'sizeRange', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'gardenSizeRange', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'priceRange', { transaction: t })
- ])
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("RealEstateRequests", "sizeRange", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "gardenSizeRange", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "priceRange", {
+ transaction: t
})
- }
-};
\ No newline at end of file
+ ]);
+ });
+ }
+};
diff --git a/app/migrations/20190530101945-range-fields.js b/app/migrations/20190530101945-range-fields.js
index caad42c..ef2a475 100644
--- a/app/migrations/20190530101945-range-fields.js
+++ b/app/migrations/20190530101945-range-fields.js
@@ -1,63 +1,147 @@
module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('RealEstateRequests', 'sizeRange', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'gardenSizeRange', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'priceRange', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'size', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'gardenSize', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'price', { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'gardenSizeMin', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'gardenSizeMax', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'sizeMin', {
- type: Sequelize.INTEGER
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'sizeMax', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'priceMin', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'priceMax', {
- type: Sequelize.INTEGER
- }, { transaction: t })
- ])
- })
- },
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("RealEstateRequests", "sizeRange", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "gardenSizeRange", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "priceRange", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "size", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "gardenSize", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "price", {
+ transaction: t
+ }),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "gardenSizeMin",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "gardenSizeMax",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "sizeMin",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "sizeMax",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "priceMin",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "priceMax",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ },
- down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('RealEstateRequests', 'gardenSizeMin', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'gardenSizeMax', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'sizeMin', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'sizeMax', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'priceMin', { transaction: t }),
- queryInterface.removeColumn('RealEstateRequests', 'priceMin', { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'priceMax', {
- type: Sequelize.STRING
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'gardenSizeRange', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'priceRange', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'size', {
- type: Sequelize.STRING
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'gardenSize', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('RealEstateRequests', 'price', {
- type: Sequelize.STRING,
- }, { transaction: t })
- ])
- })
- }
-};
\ No newline at end of file
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("RealEstateRequests", "gardenSizeMin", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "gardenSizeMax", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "sizeMin", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "sizeMax", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "priceMin", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("RealEstateRequests", "priceMin", {
+ transaction: t
+ }),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "priceMax",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "gardenSizeRange",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "priceRange",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "size",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "gardenSize",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "RealEstateRequests",
+ "price",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ }
+};
diff --git a/app/migrations/20190531111232-subscribed-boolean.js b/app/migrations/20190531111232-subscribed-boolean.js
index 2143f1c..acb4dd3 100644
--- a/app/migrations/20190531111232-subscribed-boolean.js
+++ b/app/migrations/20190531111232-subscribed-boolean.js
@@ -1,18 +1,15 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn(
- 'RealEstateRequests',
- 'subscribed',
- Sequelize.BOOLEAN
+ "RealEstateRequests",
+ "subscribed",
+ Sequelize.BOOLEAN
);
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'RealEstateRequests',
- 'subscribed'
- );
+ return queryInterface.removeColumn("RealEstateRequests", "subscribed");
}
};
diff --git a/app/migrations/20190618103020-expand-maketalert.js b/app/migrations/20190618103020-expand-maketalert.js
index 54eed96..20cf2c7 100644
--- a/app/migrations/20190618103020-expand-maketalert.js
+++ b/app/migrations/20190618103020-expand-maketalert.js
@@ -1,37 +1,70 @@
-'use strict';
+"use strict";
module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.addColumn('MarketAlerts', 'size', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'gardenSize', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'price', {
- type: Sequelize.INTEGER,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'municipality', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'region', {
- type: Sequelize.STRING,
- }, { transaction: t })
- ])
- })
- },
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "size",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "gardenSize",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "price",
+ {
+ type: Sequelize.INTEGER
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "municipality",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "region",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ },
- down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('MarketAlerts', 'size', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'gardenSize', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'price', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'municipality', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'region', { transaction: t })
- ])
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("MarketAlerts", "size", { transaction: t }),
+ queryInterface.removeColumn("MarketAlerts", "gardenSize", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("MarketAlerts", "price", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("MarketAlerts", "municipality", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("MarketAlerts", "region", {
+ transaction: t
})
- }
+ ]);
+ });
+ }
};
diff --git a/app/migrations/20190618124522-marketalerts-additional-info.js b/app/migrations/20190618124522-marketalerts-additional-info.js
index 48847d1..330faf5 100644
--- a/app/migrations/20190618124522-marketalerts-additional-info.js
+++ b/app/migrations/20190618124522-marketalerts-additional-info.js
@@ -1,33 +1,59 @@
-'use strict';
+"use strict";
module.exports = {
- up: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('MarketAlerts', 'olxUrl', { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'url', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'realestateOrigin', {
- type: Sequelize.STRING,
- }, { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'originId', {
- type: Sequelize.STRING,
- }, { transaction: t })
- ])
- })
- },
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("MarketAlerts", "olxUrl", {
+ transaction: t
+ }),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "url",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "realestateOrigin",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ ),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "originId",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ },
- down: (queryInterface, Sequelize) => {
- return queryInterface.sequelize.transaction((t) => {
- return Promise.all([
- queryInterface.removeColumn('MarketAlerts', 'url', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'realestateOrigin', { transaction: t }),
- queryInterface.removeColumn('MarketAlerts', 'originId', { transaction: t }),
- queryInterface.addColumn('MarketAlerts', 'olxUrl', {
- type: Sequelize.STRING
- }, { transaction: t })
- ])
- })
- }
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.sequelize.transaction(t => {
+ return Promise.all([
+ queryInterface.removeColumn("MarketAlerts", "url", { transaction: t }),
+ queryInterface.removeColumn("MarketAlerts", "realestateOrigin", {
+ transaction: t
+ }),
+ queryInterface.removeColumn("MarketAlerts", "originId", {
+ transaction: t
+ }),
+ queryInterface.addColumn(
+ "MarketAlerts",
+ "olxUrl",
+ {
+ type: Sequelize.STRING
+ },
+ { transaction: t }
+ )
+ ]);
+ });
+ }
};
diff --git a/app/migrations/20190621162321-add-category-to-marketalert.js b/app/migrations/20190621162321-add-category-to-marketalert.js
index d8a49f5..8f7a755 100644
--- a/app/migrations/20190621162321-add-category-to-marketalert.js
+++ b/app/migrations/20190621162321-add-category-to-marketalert.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'MarketAlerts',
- 'realEstateType',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("MarketAlerts", "realEstateType", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'MarketAlerts',
- 'realEstateType'
- );
+ return queryInterface.removeColumn("MarketAlerts", "realEstateType");
}
};
diff --git a/app/migrations/20190625120813-add-notification-sent-boolean-marketalerts.js b/app/migrations/20190625120813-add-notification-sent-boolean-marketalerts.js
index f70e6f6..339f4be 100644
--- a/app/migrations/20190625120813-add-notification-sent-boolean-marketalerts.js
+++ b/app/migrations/20190625120813-add-notification-sent-boolean-marketalerts.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'MarketAlerts',
- 'notified',
- {
- type: Sequelize.BOOLEAN
- }
- );
+ return queryInterface.addColumn("MarketAlerts", "notified", {
+ type: Sequelize.BOOLEAN
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'MarketAlerts',
- 'notified'
- );
+ return queryInterface.removeColumn("MarketAlerts", "notified");
}
};
diff --git a/app/migrations/20190628165512-add-title-to-marketalerts.js b/app/migrations/20190628165512-add-title-to-marketalerts.js
index d874f3d..6316d88 100644
--- a/app/migrations/20190628165512-add-title-to-marketalerts.js
+++ b/app/migrations/20190628165512-add-title-to-marketalerts.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'MarketAlerts',
- 'title',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("MarketAlerts", "title", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'MarketAlerts',
- 'title'
- );
+ return queryInterface.removeColumn("MarketAlerts", "title");
}
};
diff --git a/app/migrations/20190702132143-add-RREquet-uuid-to-marketalerts.js b/app/migrations/20190702132143-add-RREquet-uuid-to-marketalerts.js
index b904e6f..d8d7c5b 100644
--- a/app/migrations/20190702132143-add-RREquet-uuid-to-marketalerts.js
+++ b/app/migrations/20190702132143-add-RREquet-uuid-to-marketalerts.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'MarketAlerts',
- 'request',
- {
- type: Sequelize.STRING
- }
- );
+ return queryInterface.addColumn("MarketAlerts", "request", {
+ type: Sequelize.STRING
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'MarketAlerts',
- 'request'
- );
+ return queryInterface.removeColumn("MarketAlerts", "request");
}
};
diff --git a/app/migrations/20190710141356-add-has-location-to-marketalerts.js b/app/migrations/20190710141356-add-has-location-to-marketalerts.js
index 049efe3..237c798 100644
--- a/app/migrations/20190710141356-add-has-location-to-marketalerts.js
+++ b/app/migrations/20190710141356-add-has-location-to-marketalerts.js
@@ -1,20 +1,13 @@
-'use strict';
+"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
- return queryInterface.addColumn(
- 'MarketAlerts',
- 'hasLocation',
- {
- type: Sequelize.BOOLEAN
- }
- );
+ return queryInterface.addColumn("MarketAlerts", "hasLocation", {
+ type: Sequelize.BOOLEAN
+ });
},
down: (queryInterface, Sequelize) => {
- return queryInterface.removeColumn(
- 'MarketAlerts',
- 'hasLocation'
- );
+ return queryInterface.removeColumn("MarketAlerts", "hasLocation");
}
};
diff --git a/app/models/index.js b/app/models/index.js
index c1a3d6d..f298a63 100644
--- a/app/models/index.js
+++ b/app/models/index.js
@@ -1,27 +1,39 @@
-'use strict';
+"use strict";
-const fs = require('fs');
-const path = require('path');
-const Sequelize = require('sequelize');
+const fs = require("fs");
+const path = require("path");
+const Sequelize = require("sequelize");
const basename = path.basename(__filename);
-const env = process.env.NODE_ENV || 'development';
-const config = require(__dirname + '/../config/config.json')[env];
+const env = process.env.NODE_ENV || "development";
+const config = require(__dirname + "/../config/config.json")[env];
const db = {};
+config.username = process.env.DB_USERNAME || config.username;
+config.password = process.env.DB_PASSWORD || config.password;
+config.database = process.env.DB_NAME || config.database;
+config.port = process.env.DB_PORT || config.port;
+config.logging = parseInt(process.env.SEQUELIZE_LOGGING) ? console.log : false;
+
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
- sequelize = new Sequelize(config.database, config.username, config.password, config);
+ sequelize = new Sequelize(
+ config.database,
+ config.username,
+ config.password,
+ config
+ );
}
-fs
- .readdirSync(__dirname)
+fs.readdirSync(__dirname)
.filter(file => {
- return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
+ return (
+ file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
+ );
})
.forEach(file => {
- const model = sequelize['import'](path.join(__dirname, file));
+ const model = sequelize["import"](path.join(__dirname, file));
db[model.name] = model;
});
diff --git a/app/models/marketalert.js b/app/models/marketalert.js
index 14742ff..ddae1d5 100644
--- a/app/models/marketalert.js
+++ b/app/models/marketalert.js
@@ -1,26 +1,30 @@
-'use strict';
+"use strict";
module.exports = (sequelize, DataTypes) => {
- const MarketAlert = sequelize.define('MarketAlert', {
- url: DataTypes.STRING,
- realestateOrigin: DataTypes.STRING,
- originId: DataTypes.STRING,
- lastDate: DataTypes.STRING,
- size : DataTypes.INTEGER,
- gardenSize : DataTypes.INTEGER,
- price : DataTypes.INTEGER,
- municipality : DataTypes.STRING,
- region : DataTypes.STRING,
- realEstateType : DataTypes.STRING,
- notified : DataTypes.BOOLEAN,
- title : DataTypes.STRING,
- request: DataTypes.STRING,
- hasLocation: DataTypes.BOOLEAN,
-
- email: {
- type: DataTypes.STRING,
- allowNul: false
- }
- }, {});
+ const MarketAlert = sequelize.define(
+ "MarketAlert",
+ {
+ url: DataTypes.STRING,
+ realestateOrigin: DataTypes.STRING,
+ originId: DataTypes.STRING,
+ lastDate: DataTypes.STRING,
+ size: DataTypes.INTEGER,
+ gardenSize: DataTypes.INTEGER,
+ price: DataTypes.INTEGER,
+ municipality: DataTypes.STRING,
+ region: DataTypes.STRING,
+ realEstateType: DataTypes.STRING,
+ notified: DataTypes.BOOLEAN,
+ title: DataTypes.STRING,
+ request: DataTypes.STRING,
+ hasLocation: DataTypes.BOOLEAN,
+
+ email: {
+ type: DataTypes.STRING,
+ allowNul: false
+ }
+ },
+ {}
+ );
MarketAlert.associate = function(models) {
// associations can be defined here
};
diff --git a/app/models/realestaterequest.js b/app/models/realestaterequest.js
index e618d8d..8cedce9 100644
--- a/app/models/realestaterequest.js
+++ b/app/models/realestaterequest.js
@@ -1,26 +1,29 @@
-'use strict';
+"use strict";
module.exports = (sequelize, DataTypes) => {
-
- const RealEstateRequest = sequelize.define('RealEstateRequest', {
- uniqueId: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- allowNull: false
+ const RealEstateRequest = sequelize.define(
+ "RealEstateRequest",
+ {
+ uniqueId: {
+ type: DataTypes.UUID,
+ defaultValue: DataTypes.UUIDV4,
+ allowNull: false
+ },
+ realEstateType: DataTypes.STRING,
+ email: DataTypes.STRING,
+ region: DataTypes.STRING,
+ municipality: DataTypes.STRING,
+ sizeMin: DataTypes.INTEGER,
+ sizeMax: DataTypes.INTEGER,
+ gardenSizeMin: DataTypes.INTEGER,
+ gardenSizeMax: DataTypes.INTEGER,
+ priceMin: DataTypes.INTEGER,
+ priceMax: DataTypes.INTEGER,
+ bounding_box: DataTypes.GEOMETRY("POINT", 4326),
+ subscribed: DataTypes.BOOLEAN
},
- realEstateType: DataTypes.STRING,
- email: DataTypes.STRING,
- region: DataTypes.STRING,
- municipality: DataTypes.STRING,
- sizeMin: DataTypes.INTEGER,
- sizeMax: DataTypes.INTEGER,
- gardenSizeMin: DataTypes.INTEGER,
- gardenSizeMax: DataTypes.INTEGER,
- priceMin: DataTypes.INTEGER,
- priceMax: DataTypes.INTEGER,
- bounding_box: DataTypes.GEOMETRY('POINT', 4326),
- subscribed: DataTypes.BOOLEAN
- }, {});
+ {}
+ );
RealEstateRequest.associate = function(models) {
// associations can be defined here
};
diff --git a/app/services/crawlerService.js b/app/services/crawlerService.js
index 860afa2..1de43b8 100644
--- a/app/services/crawlerService.js
+++ b/app/services/crawlerService.js
@@ -1,85 +1,77 @@
-
const Promise = require("bluebird");
const OlxCrawler = require("../helpers/crawlers/olxClawler");
const db = require("../models/index");
-const { allMarketAlerts } = require('../helpers/db/dbHelper');
-
+const { allMarketAlerts } = require("../helpers/db/dbHelper");
async function crawlAll() {
- console.log("CRAWLER SERVICE: crawlAll");
+ try {
+ const marketAlertsFromDb = await allMarketAlerts(true);
+ const hrefs = [];
- try {
- const marketAlertsFromDb = await allMarketAlerts(true);
- const hrefs = [];
+ marketAlertsFromDb.map(marketAlert => {
+ if (hrefs[marketAlert.request] === undefined) {
+ hrefs[marketAlert.request] = [];
+ }
- marketAlertsFromDb.map(marketAlert => {
- if (hrefs[marketAlert.request] === undefined) {
- hrefs[marketAlert.request] = []
- }
+ hrefs[marketAlert.request].push(marketAlert.url);
+ });
- hrefs[marketAlert.request].push(marketAlert.url);
- })
+ const olxCrawler = new OlxCrawler(hrefs);
- console.log("CRAWLER SERVICE: GLOBAL HREFS");
- console.log(hrefs);
- const olxCrawler = new OlxCrawler(hrefs);
+ const crawlers = [olxCrawler];
- const crawlers = [
- olxCrawler,
- ];
-
- return Promise.map(crawlers, function (crawler) {
- return crawler.crawl();
- }).then(async (results) => {
+ return Promise.map(crawlers, function(crawler) {
+ return crawler.crawl();
+ }).then(async results => {
+ try {
+ const marketAlertsFromDb = await allMarketAlerts(false, true);
- try {
+ const marketAlerts = [];
+ const mergedResults = [].concat.apply([], results);
- const marketAlertsFromDb = await allMarketAlerts(false, true);
+ for (const result of mergedResults) {
+ marketAlerts.push({
+ url: result.url,
+ realestateOrigin: "OLX",
+ originId: 1,
+ size: result.size,
+ price: result.price,
+ email: result.email,
+ request: result.uuid,
+ municipality: result.municipality,
+ region: result.region,
+ gardenSize: isNaN(result.gardenSize) ? 0 : result.gardenSize,
+ realEstateType: result.realEstateType,
+ title: result.title,
+ notified: false,
+ hasLocation: result.hasLocation
+ });
+ }
- console.log("CRAWLER SERVICE: number of existing MarketAlerts from db: " + marketAlertsFromDb.length);
+ try {
+ const filteredMarketAlerts = marketAlerts.filter(
+ elem =>
+ !marketAlertsFromDb.find(({ url, request }) => {
+ return elem.url === url && elem.request === request;
+ })
+ );
- const marketAlerts = [];
- const mergedResults = [].concat.apply([], results);
-
- for (const result of mergedResults) {
- marketAlerts.push({
- url: result.url,
- realestateOrigin: "OLX",
- originId: 1,
- size: result.size,
- price: result.price,
- email: result.email,
- request: result.uuid,
- municipality: result.municipality,
- region: result.region,
- gardenSize: isNaN(result.gardenSize) ? 0 : result.gardenSize,
- realEstateType: result.realEstateType,
- title: result.title,
- notified: false,
- hasLocation: result.hasLocation
- })
- }
- console.log("CRAWLER SERVICE: Number of crawler results: " + marketAlerts.length);
-
- try {
-
- const filteredMarketAlerts = marketAlerts.filter((elem) => !marketAlertsFromDb.find(({ url, request }) => {
-
- return (elem.url === url && elem.request === request)
- }));
- console.log("CRAWLER SERVICE: Number of new crawler results: " + filteredMarketAlerts.length);
-
- await db.MarketAlert.bulkCreate(filteredMarketAlerts);
-
- } catch (e) {
- console.log("CRAWLER SERVICE: Could not bulkCreate marketalers reason: ", e);
- }
- } catch (e) {
- console.log("CRAWLER SERVICE: Error crawling. Trying next crawler! ", e);
- }
- })
- } catch (e) {
- console.error("CRAWLER SERVICE:could not fetch marketalerts ", e);
- }
-};
+ await db.MarketAlert.bulkCreate(filteredMarketAlerts);
+ } catch (e) {
+ console.log(
+ "CRAWLER SERVICE: Could not bulkCreate marketalers reason: ",
+ e
+ );
+ }
+ } catch (e) {
+ console.log(
+ "CRAWLER SERVICE: Error crawling. Trying next crawler! ",
+ e
+ );
+ }
+ });
+ } catch (e) {
+ console.error("CRAWLER SERVICE:could not fetch marketalerts ", e);
+ }
+}
module.exports = crawlAll;
diff --git a/app/services/notificationService.js b/app/services/notificationService.js
index ba3b4ab..e5625ca 100644
--- a/app/services/notificationService.js
+++ b/app/services/notificationService.js
@@ -1,29 +1,28 @@
-
const db = require("../models/index");
-const { allMarketAlerts } = require('../helpers/db/dbHelper');
-const { createMarketAlertEmailTemplate, sendBulkEmail } = require('../helpers/awsEmail');
-
+const { allMarketAlerts } = require("../helpers/db/dbHelper");
+const {
+ createMarketAlertEmailTemplate,
+ sendBulkEmail
+} = require("../helpers/awsEmail");
async function processNotifications() {
-
- try {
- const marketAlerts = await allMarketAlerts(false, false);
- console.log(marketAlerts.length)
- await createMarketAlertEmailTemplate();
- if (marketAlerts.length > 0) {
- console.log("NOTIFICATION SERVICE: Number of new alerts: " + marketAlerts.length)
- await sendBulkEmail(marketAlerts);
- } else {
- console.log("NOTIFICATION SERVICE: No new alerts");
- }
-
- await db.MarketAlert.update(
- { notified: true }, /* set attributes' value */
- { where: { notified: false } } /* where criteria */
- );
- } catch (e) {
- console.log("NOTIFICATION SERVICE: could not send notifications reason: ", e);
+ try {
+ const marketAlerts = await allMarketAlerts(false, false);
+ await createMarketAlertEmailTemplate();
+ if (marketAlerts.length > 0) {
+ await sendBulkEmail(marketAlerts);
}
+
+ await db.MarketAlert.update(
+ { notified: true } /* set attributes' value */,
+ { where: { notified: false } } /* where criteria */
+ );
+ } catch (e) {
+ console.log(
+ "NOTIFICATION SERVICE: could not send notifications reason: ",
+ e
+ );
+ }
}
module.exports = processNotifications;
diff --git a/development.env b/development.env
index 3980ba3..820ad3c 100644
--- a/development.env
+++ b/development.env
@@ -1,5 +1,15 @@
- AMAZON_ACCES_KEY_ID=(your-key-here)
- AMAZON_SECRET_ACCESS_KEY=(your-key-here)
- AMAZON_REGION=eu-west-1
- APP_URL=http://localhost:3001
- SOURCE_EMAIL=info@saburly.com
\ No newline at end of file
+DB_USERNAME=Username for the database
+DB_PASSWORD=Password for the database
+DB_NAME=Database name
+DB_PORT=Database port
+
+SEQUELIZE_LOGGING=0- no sequelize logging, 1- log to the console
+
+APP_PORT=Port for the app, defaults to 5000
+APP_BASE_URL=base url for the app
+
+AMAZON_ACCES_KEY_ID=(your-key-here)
+AMAZON_SECRET_ACCESS_KEY=(your-key-here)
+AMAZON_REGION=eu-west-1
+APP_URL=http://localhost:3001
+SOURCE_EMAIL=info@saburly.com
diff --git a/index.js b/index.js
index 5e9ad28..b9ea96c 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,6 @@
+require("dotenv").config();
+const { APP_PORT } = require("./app/config/appConfig");
+
const welcome = require("./app/controllers/welcome").getWelcome;
const {
getRealEstateTypes,
@@ -48,8 +51,6 @@ const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
-const port = process.env.PORT || 5000;
-
app.set("views", path.join(__dirname, "/app/views"));
app.set("view engine", "ejs");
app.use(layout());
@@ -180,10 +181,13 @@ app.get("/redirect/:id", redirect);
app.use("/assets", express.static("./app/public"));
-app.listen(port, () => console.log(`Example app listening on port ${port}!`));
+app.listen(APP_PORT, () =>
+ console.log(`Example app listening on port ${APP_PORT}!`)
+);
-var rule = new schedule.RecurrenceRule();
-rule.seccond = 1;
+//TODO: based on node-schedule package author, setInterval is better suited for this kind of the job
+const rule = new schedule.RecurrenceRule();
+rule.second = 1;
schedule.scheduleJob(rule, async function() {
console.log(new Date(), "Crawler service started");
await crawlAll();
diff --git a/tools/kantoni.html b/tools/kantoni.html
index e0a4091..2d28d98 100644
--- a/tools/kantoni.html
+++ b/tools/kantoni.html
@@ -1,389 +1,430 @@
-
-
-
-
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
- Mjesto
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+ Mjesto
+
+
+
+
+
+
+