Skip to content

Instantly share code, notes, and snippets.

@and7ey
Created July 21, 2024 16:09
Show Gist options
  • Save and7ey/4f5480364077287a3770070dd4bf3baa to your computer and use it in GitHub Desktop.
Save and7ey/4f5480364077287a3770070dd4bf3baa to your computer and use it in GitHub Desktop.
Добавление рейтинга отеля с TripAdvisor в результаты поиска Level Travel (скрипт для Tampermonkey)
// ==UserScript==
// @name Level Travel + Trip Advisor
// @namespace http://tampermonkey.net/
// @version 0.2
// @description Enhance Level Travel site with TripAdvisor ratings
// @author You
// @match https://level.travel/search/*
// @grant GM_xmlhttpRequest
// ==/UserScript==
const apiKeyList = ['INSERT-YOUR-API-KEY-1', 'INSERT-YOUR-API-KEY-2', 'INSERT-YOUR-API-KEY-3'];
const apiKey = apiKeyList[1];
(function() {
'use strict';
const processedElements = new Set(); // Keep track of elements that have been processed
const observer = new MutationObserver(async (mutationsList, observer) => {
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
const hotelElements = document.querySelectorAll('a[data-testid="hotel-card__title"]');
hotelElements.forEach(async (hotelElement) => {
// Check if this element has already been processed
const hotelName = hotelElement.textContent.trim();
if (!processedElements.has(hotelName)) {
console.log(hotelName);
processedElements.add(hotelName); // Mark this element as processed
const locationId = await getLocationId(hotelName);
if(locationId) {
console.log(locationId);
const details = await getLocationDetails(locationId);
console.log(details.ratingImageUrl);
console.log(details.webUrl);
addRatingImage(hotelElement, details);
}
}
});
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
})();
function setCache(key, value) {
const expiryDate = new Date();
expiryDate.setMonth(expiryDate.getMonth() + 1); // Set expiry date one month from now
const item = {
value,
expiry: expiryDate.getTime()
};
localStorage.setItem(key, JSON.stringify(item));
}
function getCache(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) {
return null;
}
const item = JSON.parse(itemStr);
const now = new Date().getTime();
if (now > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
}
async function getLocationId(hotelName) {
const cacheKey = `locationId_${hotelName}`;
let locationId = getCache(cacheKey);
if (locationId === null) { // Cache miss or expired
const url = `https://api.content.tripadvisor.com/api/v1/location/search?searchQuery=${encodeURIComponent(hotelName)}&category=hotels&language=en&key=${apiKey}`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
try {
const jsonResponse = JSON.parse(response.responseText);
locationId = jsonResponse.data[0]?.location_id; // Get location ID from response
if (locationId) {
setCache(cacheKey, locationId); // Cache the result
}
resolve(locationId);
} catch(e) {
reject(e);
}
},
onerror: function(error) {
reject(error);
}
});
});
} else {
return Promise.resolve(locationId); // Return cached location ID
}
}
async function getLocationDetails(locationId) {
const cacheKey = `details_${locationId}`;
let details = getCache(cacheKey);
if (details === null) { // Cache miss or expired
const url = `https://api.content.tripadvisor.com/api/v1/location/${locationId}/details?key=${apiKey}`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
try {
const jsonResponse = JSON.parse(response.responseText);
details = {
ratingImageUrl: jsonResponse.rating_image_url,
webUrl: jsonResponse.web_url,
reviewsCount: jsonResponse.num_reviews,
rankingData: jsonResponse.ranking_data
};
setCache(cacheKey, details); // Cache the result
resolve(details);
} catch(e) {
reject(e);
}
},
onerror: function(error) {
reject(error);
}
});
});
} else {
return Promise.resolve(details); // Return cached details
}
}
function addRatingImage(hotelElement, details) {
const img = document.createElement('img');
img.src = details.ratingImageUrl;
img.style.maxWidth = '100px';
// Wrap the image in an anchor tag with the web URL
const link = document.createElement('a');
link.href = details.webUrl;
link.target = '_blank'; // Open in a new tab
link.appendChild(img);
const div = document.createElement('div');
div.innerText = details.reviewsCount + ' reviews | ' + details.rankingData.ranking_string;
hotelElement.parentElement.insertBefore(div, hotelElement.nextSibling);
hotelElement.parentElement.insertBefore(link, hotelElement.nextSibling);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment