Skip to content

Commit

Permalink
Took places API offline
Browse files Browse the repository at this point in the history
  • Loading branch information
afoeder committed Jun 11, 2024
1 parent 24f6587 commit b0f0898
Show file tree
Hide file tree
Showing 6 changed files with 14,266 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/*-all.zip
.env
1 change: 1 addition & 0 deletions amex-dining-credit/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PLACES_API_KEY = TBD
Binary file modified amex-dining-credit/amex-dining-credit.paw
Binary file not shown.
51 changes: 51 additions & 0 deletions amex-dining-credit/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// run: `$ node --env-file=.env --experimental-fetch fetch.js
// the standard "Fetch" API is only available experimentally in Node, with the above flag we can make it available.
// handy command line infos: https://nodejs.org/en/learn/command-line/output-to-the-command-line-using-nodejs

const fs = require('node:fs');

console.log(process.env["PLACES_API_KEY"]);
return;

function amexMerchantsToPlaces(amexApiMerchants) {
return amexApiMerchants.flatMap(amexMerchant => {
if (amexMerchant.isMerchantGroup) {
// this happens when there is a "merchantGroup";
// like Gordon Ramsey etc. Those have a sub node in ".merchants"
// that again look like the merchants on the first level.
// We have to make a recursion here (yay), like:
console.log("Merchant group!", amexMerchant.name);
return amexMerchantsToPlaces(amexMerchant.merchants);
}
return {
"name": amexMerchant.name,
"address": amexMerchant.address,
"zip": amexMerchant.postcode,
"city": amexMerchant.city.title,
"googlePlaceTextQuery": `${amexMerchant.name}, ${amexMerchant.address}, ${amexMerchant.postcode} ${amexMerchant.city.title}`,
"amexRaw": amexMerchant,
}
});
}


const placesPromises =
["GB"].map(async function(country) {
const amexApiMerchants = await (
await fetch(
`https://dining-offers-prod.amex.r53.tuimedia.com/api/country/${country}/merchants`))
.json();
return {country: country, places: amexMerchantsToPlaces(amexApiMerchants)};
}
);

const places = {};

Promise.all(placesPromises).then(placesInCountries => {
placesInCountries.forEach(placesPerCountry => {
const { country, places: countryPlaces } = placesPerCountry;
places[country] = countryPlaces;
});
fs.writeFile('./places.json', JSON.stringify(places, null, 2), error => error && console.error(error));
console.info("All places written successfully.");
});
94 changes: 67 additions & 27 deletions amex-dining-credit/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,25 @@
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>AMEX Dining credit locations</title>
<style>
body { font-family: "SF Pro", sans-serif; }
</style>
</head>

<body>
<header style="display: flex; gap: 2rem; align-items: baseline">
<h1>AMEX Dining Credit restaurants</h1>

<nav>
<ul id="country-chooser" style="display: flex; gap: .5rem; list-style-type: none; padding: 0;">
<li><a href="#DE" data-center="{ lat: 51.163375, lng: 10.447683 }">DE</a></li>
<li><a href="#GB" data-center="{ lat: 54.00366, lng: -2.547855 }">GB</a></li>
</ul>
</nav>
</header>

<div id="map" style="width: 80%;height: 80vh; margin: 0 auto"></div>

<script>
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
key: "AIzaSyCsQbB1qCK4L0OkFjsSu2gsySgP9hm6sIM",
Expand All @@ -32,8 +47,34 @@

initMap();

async function fillMarkers(country = "DE") {
async function amexApiItemToPlace(item, country) {
const {Place} = await google.maps.importLibrary("places");

const request = {
//@see https://developers.google.com/maps/documentation/javascript/place-search#example
textQuery: `${item.name}, ${item.address}, ${item.postcode} ${item.city.title}`,
fields: ["id", "name", "location"],
includedType: "restaurant",
maxResultCount: 1,
region: country,
useStrictTypeFiltering: false,
};
//const {places} = await Place.searchByText(request);
let place = null;
if (places.length === 1) {
place = {location: places[0].location, name: places[0].displayName}
} else {
console.warn(`Places result for ${request.textQuery} is !== 1, places found:`, places)
}

return {
"name": item.name,
"place": place,
"amexApiRaw": item
}
}

async function fillMarkers(country = "DE") {
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

let merchantsJson;
Expand All @@ -45,31 +86,22 @@
await fetch(
`https://dining-offers-prod.amex.r53.tuimedia.com/api/country/${country}/merchants`))
.json();
merchantsJson = await Promise.all(
amexApiMerchants.map(async (item) => {
const request = {
//@see https://developers.google.com/maps/documentation/javascript/place-search#example
textQuery: `${item.name}, ${item.address}, ${item.postcode} ${item.city.title}`,
fields: ["displayName", "location", "businessStatus"],
includedType: "restaurant",
maxResultCount: 1,
region: country,
useStrictTypeFiltering: false,
};
const { places } = await Place.searchByText(request);
let place = null;
if (places.length === 1) {
place = { location: places[0].location, name: places[0].displayName }
} else {
console.warn(`Places result for ${request.textQuery} is !== 1, places found:`, places)
}

return {
"name": item.name,
"place": place,
"amexApiRaw": item
}
}));
let mapped = amexApiMerchants.map(async (item) => {
if (item.isMerchantGroup) {
// @todo: this happens when there is a "merchantGroup";
// we have to make a recursion here (yay), like:
// self.append(item.merchants)
console.log("Merchant group!", item.name, item.merchants);
return item.merchants.map(async (item) => {
return await amexApiItemToPlace(item, country)
});
}
return await amexApiItemToPlace(item, country);
});
debugger;
merchantsJson = await Promise.all(mapped);
console.log(merchantsJson);
debugger;
localStorage.setItem("amex-dining-merchants-"+country, JSON.stringify(merchantsJson));
} else {
merchantsJson = JSON.parse(cachedMerchantsData);
Expand All @@ -87,7 +119,15 @@
});
}

fillMarkers("DE");
document.getElementById("country-chooser").addEventListener("click", (event) => {
const link = event.target;
if (!link.matches("a")) return;

const language = link.getAttribute("href").match(/(?<=#)[A-Z]{2}/).at(0);
fillMarkers(language);
});

//fillMarkers("DE");

}();
</script>
Expand Down
Loading

0 comments on commit b0f0898

Please sign in to comment.