Skip to content

Instantly share code, notes, and snippets.

@thomasragger
Last active August 28, 2016 20:37
Show Gist options
  • Save thomasragger/a3fde654aa9b2571778df178a8253503 to your computer and use it in GitHub Desktop.
Save thomasragger/a3fde654aa9b2571778df178a8253503 to your computer and use it in GitHub Desktop.
getWikipediaData(query){
var dbpediaHeaders = new Headers();
//add json response type for dbpedia query
dbpediaHeaders.append("accept", "application/json");
//if the query has multiple words separated by the comma, take the first word, otherwise just use the query
query=query.indexOf(",")>0?query.split(',')[0]:query;
//if we know the query is a country, only look for countries
var featureType=this.props.type=='country'?"&feature=country":"";
//maximum listings to look through
var maxRows=5;
//query geonames to get likely results that include location data
fetch("http://api.geonames.org/wikipediaSearchJSON?maxRows="+maxRows+"&username=travelsherpa"+featureType+"&q="+query, {
method: 'get'
}).then((rawServiceResponse)=> {
return rawServiceResponse.text();
}).then((response)=> {
var wikiResponse=JSON.parse(response).geonames;
if(wikiResponse.length==0)return;
//if all checks below fail, we'll just use the first result and check for lat/lng
var wikiResult=wikiResponse[0];
var titleMatch=false;
for(var i=0;i<maxRows;i++){
//normalize results and query by converting special characters into regular characters, i.e. "á" to "a"
var cleardQuery=removeDiacritics(query.toLowerCase());
var cleardResponse=removeDiacritics(wikiResponse[i].title.toLowerCase());
// name matching::compare if we have :
// a perfect match on the regular query
// a perfect match on the normalized query
if(wikiResponse[i].title.toLowerCase()==query.toLowerCase() || cleardQuery==cleardResponse){
wikiResult=wikiResponse[i];
titleMatch=true;
break;
}
//if we have no name match, check if at least the feature-type matches, so we received a country when looking for one
//best for populated places
else if(wikiResponse[i].feature==this.props.type){
wikiResult=wikiResponse[i];
break;
}
//add another check if we at least have a result with the same countryCode
//best for populated places
else if(this.props.country&&wikiResponse[i].countryCode==this.props.country.countryCode){
wikiResult=wikiResponse[i];
break;
}
}
//now that we have the best likely result, we'll do another check if its withing a certain lat/lng range from our query
//if we requested a location, it will likely not have coordinates attached by geonames for some reason
//but also likely already passed one of the earlier tests, so we'll give it a shot without lat/lng matching.
var latLngRange=1;
var locationCheck=this.props.type=='default'?
this.props.coordinates&&
(Math.floor(this.props.coordinates.lat)<=Math.floor(wikiResult.lat)+latLngRange)&&
(Math.floor(this.props.coordinates.lat)>=Math.floor(wikiResult.lat)-latLngRange)&&
(Math.floor(this.props.coordinates.lng)<=Math.floor(wikiResult.lng+latLngRange))&&
(Math.floor(this.props.coordinates.lng)>=Math.floor(wikiResult.lng-latLngRange)):
true;
var partialTitleMatch=wikiResult.title.toLowerCase().indexOf(query.toLowerCase())>-1;
if(
locationCheck&&
(titleMatch || partialTitleMatch)
){
//to get better description copy, now query dbpedia and lets hope we get the same result as from geonames
var dbpediaQuery="";
switch(this.props.type){
case 'default':
dbpediaQuery="QueryString="+cleardQuery;
break;
case 'location':
default:
dbpediaQuery="QueryClass=PopulatedPlace&QueryString="+cleardQuery;
}
var finalDescription;
fetch("http://lookup.dbpedia.org/api/search/KeywordSearch?"+dbpediaQuery, {
method: 'get',
headers:dbpediaHeaders
}).then((rawServiceResponse)=> {
return rawServiceResponse.text();
}).then((response)=> {
var results=JSON.parse(response).results;
if(results.length){
for(var i=0;i<results.length;i++){
//another round of name matching, remove spaces from results because there were some anomalies
if(results[i].label&&results[i].label.toLowerCase().replace(/\s/g, '').indexOf(cleardQuery.replace(/\s/g, '').toLowerCase())>-1){
//get the final description
finalDescription=results[i].description;
//sometimes dbpedia returns result with the label missing from the first sentence, if thats the case, lets add it
if(finalDescription.indexOf(results[i].label)==-1)finalDescription=results[i].label+" "+finalDescription;
break;
}
}
}
//if we didn't get a good description from dbpedia, lets use the geonames one
finalDescription=finalDescription || wikiResult.summary.replace(" (...)","...");
//finally update state
this.setState({"wikipediaDescription":finalDescription,"wikiURL":wikiResult.wikipediaUrl})
})
}
}).catch(err=>console.log('fetch err',err));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment