Api's - Kitch41/Blok-Tech GitHub Wiki
For my API's i need 2 different API's:
- 1 WebAPI
- 1 regular api
After failing this project i came back to this project with a fresh look and now i see there are a few api's i can use. I did some research into Regular api's and which one i wanted to use. i ended up looking into Game API's. I want to show a few games on the page. For the webapi i decided to go with the intersection observer since it works well with the game api i chose.
I started looking for Api's on the publicapi's github. There i found a few api's but none that i needed. I started looking on the internet where i found the steamapi. This can list a lot of games a user owns. But after trying to get it to work it wouldn't give me an api key. After that i started looking for more api's until i ended at the igdb api. Its an api that can lookup a lot of information on games.
Out of the few possible api's the IGDB api is the best. The Steam list api needs a key and i wasn't able to get that. The igdb api does come with a few quirks. But i managed to get through them by using postman to test the calls. after a while the api gave me 10 items with the highest rating
Show Code
async function fetchGames(apiKey, clientId, offset, limit) {
const gamesResponse = await fetch('https://api.igdb.com/v4/games', {
method: 'POST',
headers: {
'Client-ID': clientId,
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'text/plain'
},
body: `fields name,rating,cover,summary; sort rating desc; limit ${limit}; offset ${offset};`
});
const games = await gamesResponse.json();
const coverIds = games.map(game => game.cover).filter(id => id != null);
const coversResponse = await fetch('https://api.igdb.com/v4/covers', {
method: 'POST',
headers: {
'Client-ID': clientId,
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'text/plain'
},
body: `fields url; where id = (${coverIds.join(',')});`
});
const covers = await coversResponse.json();
const coverMap = covers.reduce((acc, cover) => {
acc[cover.id] = cover.url;
return acc;
}, {});
return games.map(game => {
if (game.cover) {
game.coverUrl = coverMap[game.cover];
}
return game;
});
}The IGDB API works a little complicated. You have to first get an auth key by calling this api:
Then you can use that token to call the database and request things in the header. Like title, description and other things. The thing that makes this database a little hard is the fact you have to call a different api to get the cover images of each item. so i had to get a little creative with this.
For this code i had to use chatgpt to connect the game to the cover since i'm not good enough yet to use map and reduce this efficiently.
Show Code
gamesButton.addEventListener('click', function () {
toggleTrigger(create);
document.body.classList.add('long');
gamesButton.classList.add('active');
overviewButton.classList.remove('active');
gamesContainer.classList.remove('hidden');
overviewContainer.classList.add('hidden');
observe();
});
function toggleTrigger(state) {
const loadMoreTrigger = document.getElementById('loadMoreTrigger');
if (state === create && !loadMoreTrigger) {
const newLoadMoreTrigger = document.createElement('div');
newLoadMoreTrigger.id = 'loadMoreTrigger';
const gamesContainer = document.getElementById('gamesContainer');
gamesContainer.insertAdjacentElement('afterend', newLoadMoreTrigger);
} else if (state === remove && loadMoreTrigger) {
loadMoreTrigger.remove();
}
}
function observe() {
// intersection observer
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
loadMoreGames();
}
}, {
root: null,
rootMargin: '0px',
threshold: 1.0
});
// intersection observer observes if div is in view
observer.observe(document.querySelector('#loadMoreTrigger'));
}
async function loadMoreGames() {
try {
const response = await fetch(`/more-games?offset=${offset}&limit=10`);
const newGames = await response.json();
newGames.forEach(game => {
const truncatedSummary = game.summary.length > 200 ? game.summary.substring(0, 200) + '...' : game.summary;
const gameElement = document.createElement('div');
gameElement.classList.add('game');
gameElement.innerHTML = `
<img src="${game.coverUrl}" alt="${game.name} Cover" />
<div class="game-details">
<h2>${game.name}</h2>
<p>Rating: ${game.rating}</p>
<p>${truncatedSummary}</p>
</div>
`;
gamesContainer.appendChild(gameElement);
});
offset += 10; // Update the offset for the next batch of games
} catch (error) {
console.error('Error loading more games:', error);
}
}
});The intersection observer that i used is very simple to understand. It makes you able to perfom an Javascript action whenever a certain element comes into view on your webpage. I used this to load new games when the last few games were on the screen. This way i created a doomscrolling app with games.
At first i struggled a bit with the API since the items wouldn't load fast enough. I fixed this by moving the element up a bit and making the initial load of the amount of games a bit longer.
I looked into some other potential api's but decided not to use them afterwards. here are some:
- Fortnite API, Fortnite Stats Database ( requires API Key )
- FREETOPLAY, Free-To-Play Games Database ( harder to use )
- Steam, Steam games database ( harder to use and requires API Key )
The one API that i got close to using was the steam Web API. It is a set of tools that lets developers interact with steam. It can access game details, user info, achievements, leaderboards and ofcourse library's which is really useful for making apps that show a users game library.
When I first tried using the Steam API for my project, I got an error right away. It was super frustrating and I couldn’t figure out what was wrong. Since I was on a deadline, I decided to drop it and look for other solutions. Thats when i found my current API and this one was a lot easier to use.
Looking back now, I see that the Steam API works fine. The initial error was just an error that went away with time it seems. If i were to choose between the 2 API's i think i would've chosen the steam API since it is somewhat more extensive eventhough it is harder to use.
I decided to go with the IGDB API. It is an extensive api with covers as well as many other game details. I chose this above the others is because it is easier to use and has more relevant data.