-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5a88197
commit 47f9835
Showing
3 changed files
with
28 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,5 +11,4 @@ jobs: | |
- uses: bahmutov/npm-install@v1 | ||
- run: npm run format | ||
- run: git status | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
node_modules/ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ export async function getCoordinates(request) { | |
decodedURI = decodeURIComponentTillSame(decodedURI); | ||
return decodedURI; | ||
} | ||
function decodeURIComponentTillSame(uri) { | ||
function decodeURIComponentTillSame(uri) { // This function is often called in the code flow because sometimes Google throws highly encoded URIs. | ||
let decodedURI = decodeURIComponent(uri); | ||
while (decodedURI !== uri) { | ||
uri = decodedURI; | ||
|
@@ -50,11 +50,11 @@ export async function getCoordinates(request) { | |
}, | ||
}) | ||
.then((value1) => { | ||
return value1; | ||
return value1; | ||
}) | ||
.then(async (value2) => { | ||
var url = value2.url; | ||
if (url.endsWith('ucbcb=1')) { | ||
if (url.endsWith('ucbcb=1')) { // Now this is out of pure observation that while sending too many requests over a small span of time, Google begins to mark those a activity, while sending the expanded URI with "&ucbcb=1" parameter along with it. | ||
url = decodeURIComponent(url); | ||
originalUrl = url; | ||
} | ||
|
@@ -65,7 +65,7 @@ export async function getCoordinates(request) { | |
url = url.toString(); | ||
url = encodeURI(url); | ||
const urlObj = new URL(url); | ||
const continueParam = urlObj.searchParams.get('continue'); // sometimes while using the proxy and sending an request to the specific URI, it returns with www.google.com/sorry?continue={UNSHORTENED URI} , so this step becomes neccesary. | ||
const continueParam = urlObj.searchParams.get('continue'); // Sometimes while using the proxy and sending an request to the specific URI, it returns with https://www.google.com/sorry/index?continue={URI} , so this step becomes neccesary. | ||
if (continueParam) { | ||
url = decodeURITillSame(continueParam); | ||
url = decodeURIComponentTillSame(url); | ||
|
@@ -75,46 +75,47 @@ export async function getCoordinates(request) { | |
} | ||
var { pathname, host, hash, search } = new URL(url); | ||
|
||
var newUrl = pathname; | ||
const array = url.split('/'); | ||
const array = url.split('/'); // Stores an array which contains parts of the url which are separated if they have an "/" between them. Example:- ""https://maps.google.com?q=VGR4+5MC+Falafel+M.+Sahyoun,+Beirut,+Lebanon&ftid=0x151f16e2123697fd:0x8e6626b678863990&hl=en-US&gl=tr&entry=gps&lucs=47067413&g_ep=CAISBjYuNjQuMxgAINeCAyoINDcwNjc0MTNCAlJV" is split into array whose array[arrLength-1] will be "maps.google.com?q=VGR4+5MC+Falafel+M.+Sahyoun,+Beirut,+Lebanon&ftid=0x151f16e2123697fd:0x8e6626b678863990&hl=en-US&gl=tr&entry=gps&lucs=47067413&g_ep=CAISBjYuNjQuMxgAINeCAyoINDcwNjc0MTNCAlJV" (in some URIs this part is even smaller) as you can see this part contains plus code and address in this specific use case which will be utilised further. | ||
const arrLength = array.length; | ||
const path = pathname + search + hash; | ||
try { | ||
// PLUS CODE MECHANISM UTILISED:- In the following lines of code firstly the address is separated from plus code. The plus code we get is a shortened plus code so it won't be of use untill we expand it. For this we need to understand plus code making mechanism in itself. | ||
// For every letter of plus code from left to right the accuracy of the coordinates becomes more precise and only expanded plus codes can be converted to coordinates. For example in "849VCWC8+R9" the "849V" would be same for the city at any point but the additional "CWC8+R9" is locality specific. Read more :- https://www.dcode.fr/open-location-code | ||
// So in the below use case I first separate plus code from address, then retreive the center of the city coordinates by Nominatim API and then convert them to plus code using Google API (it gives expanded plus codes). Then I pick the initial four letters of the plus code of the city and add the rest of the plus code given in the URI and then make a plus code which corresponds to the same point/locality. (Note that this step can be shortened to a single API call via a Google API but it is costly.) | ||
console.log(url); | ||
const qParam = urlObj.searchParams.get('q'); | ||
const qParam = urlObj.searchParams.get('q'); // This gets the qParam from the above mentioned part of URL and then splits them apart into plus code and address | ||
if (qParam) { | ||
console.log(array[arrLength - 1].split('=')[1]); | ||
var address = array[arrLength - 1].split('=')[1]; | ||
link = decodeURIComponentTillSame(address); | ||
} | ||
var cityandState = link.split(',')[link.split(',').length - 2] + link.split(',')[link.split(',').length - 1]; | ||
var cityandState = link.split(',')[link.split(',').length - 2] + link.split(',')[link.split(',').length - 1]; // Now this part stores the city and state/province of which the address is of. | ||
async function gatherResponse(response) { | ||
return response.json(); | ||
} | ||
const response = await fetch(`https://geocode.maps.co/search?q=${cityandState}`); | ||
const response = await fetch(`https://geocode.maps.co/search?q=${cityandState}`); // This send an API request to retreive the center of the city. | ||
const results = await gatherResponse(response); | ||
var lat = results[0].lat; | ||
var lon = results[0].lon; | ||
const res = await fetch(`https://plus.codes/api?address=${lat},${lon}&[email protected]`); | ||
const res = await fetch(`https://plus.codes/api?address=${lat},${lon}&[email protected]`); // Utilises the latitude and longitude to retreive the plus codes of the center of the city. | ||
const result = await gatherResponse(res); | ||
var global_code = result.plus_code.global_code; | ||
var pc = link.split('+')[0] + '%2B' + link.split('+')[1]; | ||
var pc_final = global_code.substring(0, 4) + pc.substring(0, pc.length); | ||
const api = await fetch(`https://plus.codes/api?address=${pc_final}&[email protected]`); | ||
var pc_final = global_code.substring(0, 4) + pc.substring(0, pc.length); // Prepares the plus code from the city center plus code and plus code in the URI and then retreive the location coordinates from the prepared plus code. | ||
const api = await fetch(`https://plus.codes/api?address=${pc_final}&[email protected]`); | ||
console.log(`https://plus.codes/api?address=${pc_final}&[email protected]`); | ||
const final = await gatherResponse(api); | ||
lati = final.plus_code.geometry.location.lat; | ||
lng = final.plus_code.geometry.location.lng; | ||
} catch { | ||
try { | ||
console.log('hellllllooooooooooo'); | ||
// Now this method is kind of similar like the same method, the only difference here is that the address along with the plus code is stored in the back HTML code (specifically in the meta tag here with an attribute [itemprop="name"]). Cheerio library is utilised here to load the back HTML | ||
async function gatherResponse(response) { | ||
return response.text(); | ||
return response.text(); // Returns the HTML code. | ||
} | ||
var response = await fetch(url); | ||
var results = await gatherResponse(response); | ||
const $ = cheerio.load(results); | ||
let address = $('[itemprop="name"]').attr('content'); | ||
var response = await fetch(url); | ||
var results = await gatherResponse(response); // Result contains the HTML code. | ||
const $ = cheerio.load(results); // It loads the HTML code via the library which we can further access like an object. | ||
let address = $('[itemprop="name"]').attr('content'); // The address is stored in this. Next the same procedure is followed just like in the above use case. | ||
console.log(address); | ||
let plucodeAddress = address.split('·')[1]; | ||
let plusCode = plucodeAddress.substring(1, 5) + '%2B' + plucodeAddress.substring(6, 9); | ||
|
@@ -146,6 +147,7 @@ export async function getCoordinates(request) { | |
lati = final.plus_code.geometry.location.lat; | ||
lng = final.plus_code.geometry.location.lng; | ||
} catch { | ||
// Now in this use case the HTML code in the backend has an URI in it which has the coordinates (For example for URI:- "https://maps.google.com/maps/api/staticmap?center=28.3875877%2C79.4334719&zoom=16&size=900x900&language=en&markers=28.3873906%2C79.4332585&sensor=false&client=google-maps-frontend&signature=n8UGrbdCp1219NbZQizcgHHBddE" The backend URI which has coordinates is like "https://maps.google.com/maps/api/staticmap?center=28.3875877%2C79.4334719&zoom=16&size=900x900&language=en&markers=28.3873906%2C79.4332585&sensor=false&client=google-maps-frontend&signature=n8UGrbdCp1219NbZQizcgHHBddE") which has ";markers" in it (it is unique in the entire HTML code). So we extract this | ||
if (host === 'www.google.com' || host === 'maps.google.com') { | ||
async function gatherResponse(response) { | ||
return response.text(); | ||
|
@@ -155,13 +157,14 @@ export async function getCoordinates(request) { | |
console.log(results) | ||
try { | ||
console.log('first'); | ||
var position = results.indexOf(';markers'); | ||
var link = results.substring(position - 1, position + 70); | ||
link = link.split('=')[1]; | ||
lati = link.split('%2C')[0]; | ||
var position = results.indexOf(';markers'); // Gets the index of ;markers in the code. | ||
var link = results.substring(position - 1, position + 70); // extracts the string nearby it | ||
link = link.split('=')[1]; // Gets the latitude and longitude from it | ||
lati = link.split('%2C')[0]; | ||
lng = link.split('%2C')[1].split('%7C')[0]; | ||
} catch { | ||
try { | ||
// Now this is similar to the above use cases, we get the coordinates from an URI in the HTML code which starts with "https://www.google.com/maps/preview/place/" | ||
console.log('second') | ||
position = results.indexOf('https://www.google.com/maps/preview/place/'); | ||
link = results.substring(position - 1, position + 250); | ||
|
@@ -174,6 +177,7 @@ export async function getCoordinates(request) { | |
lati = lati.toString() | ||
lng = lng.toString() | ||
} catch { | ||
// Again similar, we get the coordinates from an URI in the HTML code which starts with "https://maps.google.com/maps/api/staticmap?center=" | ||
console.log('third') | ||
position = results.indexOf('https://maps.google.com/maps/api/staticmap?center='); | ||
link = results.substring(position - 1, position + 250); | ||
|
@@ -182,6 +186,7 @@ export async function getCoordinates(request) { | |
lng = latlng.split('%2C')[1].split('&')[0]; | ||
} | ||
} | ||
// Below are the simlar use cases with different search strings. The point of this being implemented is that there are some cases when only one URI is present in the backend which has the coordinates and we can't predict that so ww have to check them one by one using try catch statements to avoid errors. | ||
catch { | ||
try { | ||
console.log('fourth') | ||
|