Changeset cd64b06
- Timestamp:
- 01/11/25 01:23:10 (4 days ago)
- Branches:
- master
- Children:
- 0a7426e
- Parents:
- 1c51912
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
backend/GlobeGuru-backend/src/main/java/DatabaseUtil.java
r1c51912 rcd64b06 151 151 "FROM options o " + 152 152 "LEFT JOIN optionDetails od ON o.id = od.optionId " + 153 "WHERE (o.country LIKE ? OR o.hotelName LIKE ?)"; 153 "WHERE (o.country LIKE ? OR o.hotelName LIKE ?) " + 154 "AND od.type IS NOT NULL " + 155 "AND od.board IS NOT NULL " + 156 "AND od.price > 0"; 154 157 155 158 if (dateQuery != null && !dateQuery.isEmpty() && !dateFlag) { … … 200 203 return options; 201 204 } 205 202 206 203 207 -
backend/GlobeGuru-backend/src/main/java/FrontendHandler.java
r1c51912 rcd64b06 130 130 return; 131 131 } 132 133 132 Server.sendResponse(exchange, 200, mapper.writeValueAsString(options)); 134 133 } -
backend/GlobeGuru-backend/src/main/java/ScraperThread.java
r1c51912 rcd64b06 96 96 } else if (optionSet.add(option)) { 97 97 uniqueOptions.add(option); 98 DatabaseUtil.saveOptionToDatabase(option); 98 option.setId(DatabaseUtil.saveOptionToDatabase(option)); 99 scrapeOptionInfo(option); 99 100 System.out.println("Parsed " + option); 100 101 } … … 149 150 150 151 String board = roomOption.select(".rezervacija-objekt").text(); 151 if(board.length() > 2) {152 board = board.substring(0, 2);152 if(board.length() > 2) { 153 board = board.substring(0, 2); 153 154 } 154 if(board.isEmpty() || type.isEmpty()){ 155 continue; 156 } 155 if(board.isEmpty() || type.isEmpty()) continue; 156 157 157 Elements amenityElement = roomOption.select(".objekt-opis"); 158 158 String amenity = (amenityElement != null ? amenityElement.text() : ""); … … 166 166 DatabaseUtil.saveOptionDetails(option.getId(), type,board,amenity, price); 167 167 } 168 } 169 else if(url.contains("booking.escapetravel.mk")){ 170 System.out.println("Scraping info for " + url); 171 172 driver.get(url); 173 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //data fetch 174 String pageSource = driver.getPageSource(); 175 Document doc = Jsoup.parse(pageSource); 176 Elements roomOptions = doc.select("#hotel-rooms-container .hotel-room-row"); 177 for(Element roomOption : roomOptions){ 178 String type = roomOption.select("td.align-middle").first().text(); 179 String board = roomOption.select("td.align-middle.text-primary.lead").text(); 180 if (board.isEmpty() || type.isEmpty()) continue; 181 String priceText = roomOption.select("td.align-middle.text-end .text-success.d-block.lead").text().replace("€", "").trim(); 182 float price; 183 if (!priceText.isEmpty()) { 184 price = Float.parseFloat(priceText.replace(",", "")); 185 } else continue; 186 187 Elements amenityElements = doc.select("div.row > div.col-6.col-md-3.col-xl-2"); 188 StringBuilder amenities = new StringBuilder(); 189 for (Element amenityElement : amenityElements) { 190 amenities.append(amenityElement.text()).append(", "); 191 } 192 if (!amenities.isEmpty()) { 193 amenities.setLength(amenities.length() - 2); 194 } 195 System.out.println(type + board + price + amenities); 196 DatabaseUtil.saveOptionDetails(option.getId(), type, board, amenities.toString(), price); 197 } 198 168 199 } 169 200 } -
backend/GlobeGuru-backend/src/main/java/Server.java
r1c51912 rcd64b06 196 196 197 197 public static void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { 198 byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); 198 199 exchange.getResponseHeaders().add("Cross-Origin-Opener-Policy", "unsafe-none"); 199 200 exchange.getResponseHeaders().add("Cross-Origin-Embedder-Policy", "require-corp"); 200 201 exchange.getResponseHeaders().add("Content-Type", "application/json"); 201 exchange.sendResponseHeaders(statusCode, response.length()); 202 exchange.getResponseBody().write(response.getBytes()); 203 exchange.getResponseBody().close(); 204 } 205 202 exchange.getResponseHeaders().add("Transfer-Encoding", "chunked"); 203 exchange.sendResponseHeaders(statusCode, 0); 204 try (OutputStream os = exchange.getResponseBody()) { 205 os.write(responseBytes); 206 } 207 } 206 208 } 207 209 -
backend/GlobeGuru-backend/src/main/resources/URLsJSON.json
r1c51912 rcd64b06 2 2 "agencyurls": 3 3 [ 4 "https://magelantravel.mk/" 5 4 "https://magelantravel.mk/", 5 "https://booking.escapetravel.mk/" 6 6 ] 7 7 } -
backend/GlobeGuru-backend/target/classes/URLsJSON.json
r1c51912 rcd64b06 2 2 "agencyurls": 3 3 [ 4 "https://magelantravel.mk/" 5 4 "https://booking.escapetravel.mk/" 6 5 ] 7 6 } -
backend/GlobeGuru-backend/target/classes/lastUpdateTime.json
r1c51912 rcd64b06 1 1 { 2 "lastUpdateTime" : "2025-01-1 0T18:31:22.019011800"2 "lastUpdateTime" : "2025-01-11T00:07:21.694581100" 3 3 } -
frontend/css.css
r1c51912 rcd64b06 15 15 right: 20px; 16 16 } 17 17 .infoDiv{ 18 width:400px; 19 } 18 20 .login-button { 19 21 background-color: #007bff; -
frontend/js/formHandler.js
r1c51912 rcd64b06 4 4 5 5 form.addEventListener('submit', function(event) { 6 event.preventDefault(); // Prevent the default form submission6 event.preventDefault(); 7 7 8 // Collect form data9 8 const formData = new FormData(form); 10 9 const data = {}; … … 12 11 let errorMessage = ""; 13 12 14 // Validate form data15 13 formData.forEach((value, key) => { 16 14 data[key] = value; … … 36 34 loadingOverlay.style.display = 'flex'; 37 35 38 // Send form data to the server39 36 fetch('/submit', { 40 37 method: 'POST', … … 44 41 body: JSON.stringify(data) 45 42 }) 46 .then(response => response.json()) 43 .then(response => { 44 if (!response.ok) { 45 throw new Error('Network response was not ok ' + response.statusText); 46 } 47 return response.json(); 48 }) 47 49 .then(data => { 48 50 loadingOverlay.style.display = 'none'; 49 50 51 const dataList = document.getElementById('givenOptions'); 51 52 dataList.innerHTML = ''; … … 56 57 wrapper.appendChild(text); 57 58 dataList.appendChild(wrapper); 59 } else { 60 data.forEach(item => { 61 const optionDiv = document.createElement('div'); 62 optionDiv.classList.add('option'); 63 64 const img = document.createElement('img'); 65 img.classList.add('image'); 66 img.src = item.imgSrc || ''; 67 optionDiv.appendChild(img); 68 const WrapperDiv = document.createElement('div'); 69 optionDiv.appendChild(WrapperDiv); 70 71 const nameParagraph = document.createElement('p'); 72 nameParagraph.id = 'name'; 73 nameParagraph.textContent = item.hotelName || 'N/A'; 74 WrapperDiv.appendChild(nameParagraph); 75 76 const countryParagraph = document.createElement('p'); 77 countryParagraph.id = 'country'; 78 countryParagraph.style.fontSize = '20px'; 79 countryParagraph.textContent = item.country || 'N/A'; 80 WrapperDiv.appendChild(countryParagraph); 81 82 const dateParagraph = document.createElement('h2'); 83 dateParagraph.id = 'date'; 84 dateParagraph.textContent = item.dateRange || 'N/A'; 85 WrapperDiv.appendChild(dateParagraph); 86 87 const peopleParagraph = document.createElement('p'); 88 peopleParagraph.id = 'numPeople'; 89 peopleParagraph.textContent = item.numPeople === 1 ? item.numPeople + " лице" : item.numPeople + " лица"; 90 WrapperDiv.appendChild(peopleParagraph); 91 92 const priceHeading = document.createElement('h1'); 93 priceHeading.textContent = 'Цена:'; 94 WrapperDiv.appendChild(priceHeading); 95 const priceParagraph = document.createElement('h2'); 96 priceParagraph.id = 'price'; 97 priceParagraph.textContent = (item.price || 0) + " EUR"; 98 WrapperDiv.appendChild(priceParagraph); 99 100 const infoDiv = document.createElement('div'); 101 infoDiv.classList.add("infoDiv"); 102 const typeRoom = document.createElement('p'); 103 typeRoom.textContent = "Тип на соба: " + (item.type || 'N/A'); 104 infoDiv.appendChild(typeRoom); 105 const plan = document.createElement('p'); 106 plan.textContent = "Услуга: " + (item.board || 'N/A'); 107 infoDiv.appendChild(plan); 108 const amenities = document.createElement('p'); 109 amenities.textContent = item.amenities && item.amenities.length > 0 ? "Поволности: " + item.amenities : "Нема информации од агенцијата за вклучените поволности."; 110 infoDiv.appendChild(amenities); 111 optionDiv.appendChild(infoDiv); 112 113 const link = document.createElement('a'); 114 link.id = 'link'; 115 link.href = item.link || '#'; 116 link.target = '_blank'; 117 118 const button = document.createElement('button'); 119 button.classList.add('btn', 'login-button'); 120 button.textContent = 'Линк до страна'; 121 const btnWrapDiv = document.createElement('div'); 122 btnWrapDiv.classList.add('btnWrapper'); 123 const favBtn = document.createElement('button'); 124 favBtn.classList.add('favBtn', 'btn'); 125 favBtn.id = 'favBtnId'; 126 favBtn.textContent = 'Додадете во омилени'; 127 favBtn.setAttribute('data-option-id', item.id); 128 favBtn.addEventListener('click', function () { 129 const optionId = this.getAttribute('data-option-id'); 130 saveFavoriteOption(optionId); 131 }); 132 133 btnWrapDiv.appendChild(link); 134 link.appendChild(button); 135 btnWrapDiv.appendChild(favBtn); 136 137 optionDiv.appendChild(btnWrapDiv); 138 dataList.appendChild(optionDiv); 139 }); 140 console.log('Finished processing data.'); 58 141 } 59 data.forEach(item => {60 61 const optionDiv = document.createElement('div');62 optionDiv.classList.add('option');63 64 //image65 const img = document.createElement('img');66 img.classList.add('image');67 img.src = item.imgSrc;68 optionDiv.appendChild(img);69 const WrapperDiv = document.createElement('div');70 optionDiv.appendChild(WrapperDiv);71 //hotel72 const nameParagraph = document.createElement('p');73 nameParagraph.id = 'name';74 nameParagraph.textContent = item.hotelName;75 WrapperDiv.appendChild(nameParagraph);76 //Destination77 const countryParagraph = document.createElement('p');78 countryParagraph.id = 'country';79 countryParagraph.style.fontSize = '20px';80 countryParagraph.textContent = item.country;81 WrapperDiv.appendChild(countryParagraph);82 const dateParagraph = document.createElement('h2');83 dateParagraph.id = 'date';84 dateParagraph.textContent = item.dateRange;85 WrapperDiv.appendChild(dateParagraph);86 const peopleParaghraph = document.createElement('p');87 peopleParaghraph.id = 'numPeople';88 if(item.numPeople === 1){89 peopleParaghraph.textContent = item.numPeople + " лице";90 }91 else peopleParaghraph.textContent = item.numPeople + " лица";92 WrapperDiv.appendChild(peopleParaghraph);93 //price94 const priceHeading = document.createElement('h1');95 priceHeading.textContent = 'Цена:';96 WrapperDiv.appendChild(priceHeading);97 const priceParagraph = document.createElement('h2');98 priceParagraph.id = 'price';99 priceParagraph.textContent = item.price + "EUR";100 WrapperDiv.appendChild(priceParagraph);101 102 103 const infoDiv = document.createElement('div');104 const typeRoom = document.createElement('p');105 typeRoom.textContent = "Тип на соба: " + item.type;106 infoDiv.appendChild(typeRoom);107 const plan = document.createElement('p');108 plan.textContent = "Услуга: " + item.board;109 infoDiv.appendChild(plan);110 const amenities = document.createElement('p');111 if(item.amenities.length === 0){112 amenities.textContent = "Нема информации од агенцијата за вклучените поволности. ";113 }else amenities.textContent = "Поволности: " + item.amenities;114 infoDiv.appendChild(amenities);115 optionDiv.appendChild(infoDiv);116 117 118 // link and button119 const link = document.createElement('a');120 link.id = 'link';121 link.href = item.link; // Use item.link if available122 link.target = '_blank'; // Open link in new tab123 124 const button = document.createElement('button');125 button.classList.add('btn', 'login-button');126 button.textContent = 'Линк до страна';127 const btnWrapDiv = document.createElement('div');128 btnWrapDiv.classList.add('btnWrapper');129 const favBtn = document.createElement('button');130 favBtn.classList.add('favBtn','btn');131 favBtn.id = 'favBtnId';132 favBtn.textContent = 'Додадете во омилени';133 favBtn.setAttribute('data-option-id', item.id);134 favBtn.addEventListener('click', function () {135 const optionId = this.getAttribute('data-option-id');136 saveFavoriteOption(optionId);137 });138 139 btnWrapDiv.appendChild(link);140 link.appendChild(button);141 btnWrapDiv.appendChild(favBtn);142 143 optionDiv.appendChild(btnWrapDiv);144 dataList.appendChild(optionDiv);145 });146 142 updateFavoriteButtons(); 147 143 })
Note:
See TracChangeset
for help on using the changeset viewer.