Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 48 additions & 27 deletions server/internal/metadata/igdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ interface IGDBCompanyWebsite extends IGDBItem {
}

interface IGDBCover extends IGDBItem {
url: string;
image_id: string;
}

interface IGDBSearchStub extends IGDBItem {
Expand Down Expand Up @@ -179,15 +179,15 @@ export class IGDBProvider implements MetadataProvider {

if (response.status !== 200)
throw new Error(
`Error in IDGB \nStatus Code: ${response.status}\n${response.data}`,
`Error in IGDB \nStatus Code: ${response.status}\n${response.data}`,
);

this.accessToken = response.data.access_token;
this.accessTokenExpiry = DateTime.now().plus({
seconds: response.data.expires_in,
});

logger.info("IDGB done authorizing with twitch");
logger.info("IGDB done authorizing with twitch");
}

private async refreshCredentials() {
Expand Down Expand Up @@ -246,39 +246,43 @@ export class IGDBProvider implements MetadataProvider {
return <T[]>response.data;
}

private async _getMediaInternal(mediaID: IGDBID, type: string) {
private async _getMediaInternal(mediaID: IGDBID, type: string, size: string = "t_thumb" ) {
if (mediaID === undefined)
throw new Error(
`IGDB mediaID when getting item of type ${type} was undefined`,
);

const body = `where id = ${mediaID}; fields url;`;
const body = `where id = ${mediaID}; fields image_id;`;
const response = await this.request<IGDBCover>(type, body);

let result = "";
if (!response.length || !response[0].image_id) {
throw new Error(`No image_id found for ${type} with id ${mediaID}`);
}

response.forEach((cover) => {
if (cover.url.startsWith("https:")) {
result = cover.url;
} else {
// twitch *sometimes* provides it in the format "//images.igdb.com"
result = `https:${cover.url}`;
}
});
const imageId = response[0].image_id;
const result = `https://images.igdb.com/igdb/image/upload/${size}/${imageId}.jpg`;

return result;
}

private async getCoverURL(id: IGDBID) {
return await this._getMediaInternal(id, "covers");
return await this._getMediaInternal(id, "covers", "t_cover_big");
}

private async getArtworkURL(id: IGDBID) {
return await this._getMediaInternal(id, "artworks");
return await this._getMediaInternal(id, "artworks", "t_1080p");
}

private async getScreenshotURL(id: IGDBID) {
return await this._getMediaInternal(id, "screenshots", "t_1080p");
}

private async getIconURL(id: IGDBID) {
return await this._getMediaInternal(id, "covers", "t_thumb");
}

private async getCompanyLogoURl(id: IGDBID) {
return await this._getMediaInternal(id, "company_logos");
return await this._getMediaInternal(id, "company_logos", "t_original");
}

private trimMessage(msg: string, len: number) {
Expand Down Expand Up @@ -327,7 +331,7 @@ export class IGDBProvider implements MetadataProvider {
let icon = "";
const cover = response[i].cover;
if (cover !== undefined) {
icon = await this.getCoverURL(cover);
icon = await this.getIconURL(cover);
} else {
icon = "";
}
Expand Down Expand Up @@ -355,23 +359,26 @@ export class IGDBProvider implements MetadataProvider {
const currentGame = (await this.request<IGDBGameFull>("games", body)).at(0);
if (!currentGame) throw new Error("No game found on IGDB with that id");

context?.logger.info("Using IDGB provider.");
context?.logger.info("Using IGDB provider.");

let iconRaw;
let iconRaw, coverRaw;
const cover = currentGame.cover;

if (cover !== undefined) {
context?.logger.info("Found cover URL, using...");
iconRaw = await this.getCoverURL(cover);
iconRaw = await this.getIconURL(cover);
coverRaw = await this.getCoverURL(cover);
} else {
context?.logger.info("Missing cover URL, using fallback...");
iconRaw = jdenticon.toPng(id, 512);
coverRaw = iconRaw
}

const icon = createObject(iconRaw);
const coverID = createObject(coverRaw);
let banner;

const images = [icon];
const images = [coverID];
Comment on lines -374 to +381
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to include the icon in the images array as that's meant to include every imagine iirc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not included in the other metadata fetchers :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If icon isn't used anywhere then can you remove it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in the return value of fetchgame(), but it is not part of the images array. The icons are used in the side menu of the library page
image
and as a browser tab icon in a game page inside the store
image
If the icon was part of the images array it would appear together with the other images as an option to add it to carousel, which is not very useful IMO.

for (const art of currentGame.artworks ?? []) {
const objectId = createObject(await this.getArtworkURL(art));
if (!banner) {
Expand All @@ -384,6 +391,11 @@ export class IGDBProvider implements MetadataProvider {
banner = createObject(jdenticon.toPng(id, 512));
}

for (const screenshot of currentGame.screenshots ?? []) {
const objectId = createObject(await this.getScreenshotURL(screenshot));
images.push(objectId);
}

context?.progress(20);

const publishers: CompanyModel[] = [];
Expand Down Expand Up @@ -452,13 +464,22 @@ export class IGDBProvider implements MetadataProvider {

const genres = await this.getGenres(currentGame.genres);

const deck = this.trimMessage(currentGame.summary, 280);
let description = "";
let shortDescription = "";

if (currentGame.summary.length > (currentGame.storyline?.length ?? 0)) {
description = currentGame.summary;
shortDescription = this.trimMessage(currentGame.storyline ?? currentGame.summary, 280);
} else {
description = currentGame.storyline ?? currentGame.summary;
shortDescription = this.trimMessage(currentGame.summary, 280);
}

const metadata = {
id: currentGame.id.toString(),
name: currentGame.name,
shortDescription: deck,
description: currentGame.summary,
shortDescription,
description,
released,

genres,
Expand All @@ -471,7 +492,7 @@ export class IGDBProvider implements MetadataProvider {

icon,
bannerId: banner,
coverId: icon,
coverId: coverID,
images,
};

Expand Down Expand Up @@ -519,4 +540,4 @@ export class IGDBProvider implements MetadataProvider {

return undefined;
}
}
}