-
Notifications
You must be signed in to change notification settings - Fork 0
External API
Bronnen:
- The Coding Train (2019, May 17). Working With Data & APIs in Javascript [Video series]. Youtube. https://www.youtube.com/watch?v=wxbQP1LMZsw&list=PLRqwX-V7Uu6YxDKpFzf_2D84p0cyk4T7X
- IGDB API Documentation. (n.d.). Retrieved March 24, 2020, from https://api-docs.igdb.com/
-
Geen documentatie beschikbaar In het geval van Chicken Coop API is er geen officiële documentatie beschikbaar. Het enige waar je het mee kan doen is wat aangeboden wordt via Rapid API.
-
Niet alle API's leveren daadwerkelijk games op In het geval van de SteamWeb API kan leveren alle endpoints data op die niet persé iets vertelt over de games.
-
Veel API's zijn gericht op één game Deze API's leveren dus allerlei informatie over de game waar ze van zijn. In het geval van Pokemon, zouden ze dus informatie beschikbaar geven over de pokemon die er zijn, aanvallen, waar je ze kunt vinden, etc.
-
Onduidelijke documentatie Dit was het geval bij RAWG. Het was een complete API, die gericht was op games en informatie over games beschikbaar stellen. Het probleem was dat de documentatie matig was. Er ontbrak een duidelijk voorbeeld van het gebruik van de API en de calls. Alle voorbeelden die ik kon vinden hadden enkel placeholders.
De gekozen API is uiteindelijk die van IGDB geworden. Deze API biedt ontzettend veel mogelijkheden qua endpoiints en dus data. Daarnaast is de documentatie enorm volledig.
De documentatie biedt voorbeelden op get requests op te stellen. Er is een voorbeeld voor een POSTMAN setup, met daarnaast verschillende queries die je kan opstellen om zo de gewenste data te vinden.
Hetzelfde geldt voor wanneer je kijkt naar het toepassen van de verschillende endpoints. Er worden voorbeelden gegeven van hoe je in verschillende toepassingen gebruik kan maken van de API.

De API maakt gebruik van Axios om een verbinding te creeëren tussen de applicatie en hun server. Axios is een NPM pakket om http requests te sturen vanaf node.js applicaties. Het doet in dit geval hetzelfde werk als unirest en request voor node.js. Het handelt http requests volgens de Promise principe en verandert data automatisch naar JSON.
Het gebruik van Axios is ontzettend makkelijk. Veel makkelijker dan gebruik maken van native http requests in node.js of zelfs het gebruik van request & unirest. Dit is ook een van de redenen dat ik deze API ben gaan proberen. Voor toekomstig gebruik en verdere ontwikkeling lijkt het erg geschikt.
const axiosApiCall = (cb) => {
axios({
url: "https://api-v3.igdb.com/games",
method: 'POST',
headers: {
'Accept': 'application/json',
'user-key': userKey
},
// "where parent_game = n & version_parent = n & themes != (42)" Is from the developer of the algorithm.
// This is an easy way to approach the real algorithm. Source is the IGDB discord, in their #api channelby user "⚔ Loefvet | IGDB", a developer for IGDB
data: "fields name,id,rating,popularity,summary,total_rating_count,screenshots.*; where parent_game = n & version_parent = n & themes != (42) & rating_count > 150; sort rating desc; limit 100;"
})
.then(response => {
const topGames = JSON.stringify(response.data, null, 4) //(response.data, null, 6)
fs.writeFile('./api/outputGames.json', topGames, (err) => {
if (err) {
console.log('An error occured while writing the JSON file')
console.log(err)
}
else {
console.log('The JSON was saved')
}
})
})
.catch(err => {
console.error(err)
})
}fields name,id,rating,popularity,summary,total_rating_count,screenshots.image_id; sort rating desc; limit 100;"Ik moest een manier vinden om de top 100 games van IGDB te banaderen. Voor de API om te begrijpen waar voor gevraagd wordt, bouw je in de data-key een query. In de documentatie kan je meer informatie vinden over welke endpoints welke tags accepteren. In eerste instantie heb ik de query hieronder geprobeerd. Bij fields geef je als eerst aan welke data je terug wil van de API, waarna voorwaarden kunnen worden gesteld waar de games dan aan getoetst worden. Dit leek dus vrij simpel, ik wil de 100 games met de hoogste rating, van hoog naar laag geordend. Dit waren de resultaten.
{
"id": 132135,
"name": "The Lost World: Jurassic Park (Arcade)",
"popularity": 1.0
},
{
"id": 132134,
"name": "Dragon Riders: Chronicles of Pern",
"popularity": 1.0
},
{
"id": 132133,
"name": "Nameless Cat",
"popularity": 1.0
},
{
"id": 132132,
"name": "FARSTAR: Exodus",
"popularity": 1.0
},
{
"id": 132131,
"name": "Plants Vs. Zombies 2: Project Eclise",
"popularity": 1.0
},
{
"id": 132130,
"name": "Tailgunner",
"popularity": 1.0
}Ik merkte dat ergens de query brak, want de resultaten leken niets op de daadwerkelijke top 100 van IGDB. Vervolgens heb ik de query aangepast naar zoeken op popularity. Hierbij kreeg ik wat bekendere titels, zoals Monster Hunter World, CyberPunk 2077, Remnant from the Ashes. Dit zijn games die daadwerkelijk in de top 100 zitten, maar echter waren de resultaten niet in volgorde. Toen ben ik op zoek naar meer informatie gegaan over de API. Waarna ik erachter kwam dat IGDB een officiële discord heeft met een API kanaal speciaal voor developers.
Op de discord kwam ik snel posts van de developers tegen, waarin aangeraden werd om te zoeken op rating met rating_count > x. Dit zou zorgen dat games die eventueel eenmalig een perfecte score hadden gekregen van de developers zelf of vrienden uit de resultaten gefilterd zouden worden. Er wordt een minimum aantal ratings gevraagd om te voldoen aan de top 100. Dit leverde vrij goede resultaten. Echter was er één groot probleem hiermee. Zie hieronder:
{
"id": 22439,
"name": "The Witcher 3: Wild Hunt - Game of the Year Edition",
"popularity": 24.4035634256982,
"rating": 98.615065244241,
"total_rating_count": 215
},
{
"id": 13166,
"name": "The Witcher 3: Wild Hunt - Blood and Wine",
"popularity": 5.23493052465015,
"rating": 97.02594734689382,
"total_rating_count": 225
},
{
"id": 1942,
"name": "The Witcher 3: Wild Hunt",
"popularity": 134.9575392270916,
"rating": 96.339903738467,
"total_rating_count": 2126
}De eerste drie resultaten waren van The Witcher, wat ook echt een goede game is. Maar er zijn twee verschillende versies van hetzelfde spel aangegeven, namelijk de originele release op 3 en vervolgens de GOTY editie op nummer 1. Dit moest gefilterd worden. Hiervoor ben ik verder gaan kijken in de Discord naar eventuele tips. Toen kwam ik dit tegen:
fields name,id,rating,popularity,summary,total_rating_count,screenshots.image_id;
// In het specifiek deze lijn
where parent_game = n & version_parent = n & themes != (42) & rating_count > 150;
sort rating desc; limit 100;"Met parent_game = n vraag je om de main game uit een serie gerelateerde games, dlc's of bundels. Deze voorwaarde stelt dat enkel main games uit een serie door de API worden geselecteerd. Dus in dit geval valt he Witcher 3: Wild Hunt - Blood and Wine weg.
Voor version_parent = n stel je de voorwaarde dat als er verschillende versies of edities zijn van een game, dat je vraagt om de originele versie van het spel. Dit is enigzins arbitrair, een GOTY edition is immers ook een originele versie. Maar vanuit de development voor de API is deze keuze gemaakt. De resultaat van deze voorwaarde is dus dat The Witcher 3: Wild Hunt - Game of the Year Edition ook uit de resultaten verdwijnt.
Zo komen we eigenlijk uit op de gehele query die zorgt voor dat we een top 100 games lijst kunnen krijgen die representeert wat IGDB daadwerkelijk gebruikt. Dit is nog steeds een benadering van de daadwerkelijke algoritme. De developers op de Discord zeiden dat ze "het niet zeker wisten". Maar ik geloof dat ze niet de gehele kennis wilden weg geven. Wat ik ook wel begrijp. Dit zou het eventueel vatbaar maken voor veiligheidsrisico's.
Voor het project is het belangrijk dat de lijst met top 100 games up-to-date blijft. Wat ik hiermee bedoel is dat op het moment dat de volgorde van de top 100 verandert, in de app dezelfde resultaten weergegeven worden.
Een plotselinge verandering kan mogelijk veroorzaakt worden door bijvoorbeeld de release van een nieuw spel. Dit nieuwe spel kan vele ratings krijgen en op eens verandert dus de top 100 lijst.
Om de lijst up-to-date te houden heb ik de axios call als een functie geschreven die de mogelijkheid geeft voor een callback.
// USER ROUTING (./routes/user.js)
const axiosApiCall = (cb) => {
axios({
(...)
})
.then(response => {
(...)
})
.catch(err => {
(...)
})
}
module.exports = axiosApiCallVervolgens door gebruik te maken van de ingebouwde functie setInterval, roep ik de functie telkens aan op basis van een variabele genaamd apiTime. Deze zit in .env gestopt om mogelijke veiligheidsrisico's te beperken. Momenteel staat deze waarde op één minuut. Het zit bewust op een relatief lage waarde om zo de werking te kunnen demonstreren.
// INDEX.JS
// Timing API call
const apiTimer = setInterval(function () {
axiosApiCall()
}, apiTime)
apiTimer
