fmt
Unit Tests with docker compose / unit-test (pull_request) Successful in 23s Details
Unit Tests with docker compose / unit-test (push) Successful in 21s Details
Build image / build (push) Failing after 23s Details

This commit is contained in:
Alie 2024-04-17 20:04:43 +02:00
parent 1aacac9c41
commit 642e075721
17 changed files with 208 additions and 193 deletions

View File

@ -8,8 +8,8 @@ class ImageController {
const image = await ImageService.get();
res.json(image);
} catch (error: any) {
logger.error(error)
res.status(500).json({ "error": `Internal server error: ${error}` });
logger.error(error);
res.status(500).json({ error: `Internal server error: ${error}` });
}
}
}

View File

@ -10,7 +10,7 @@ const server = app.listen(PORT, () =>
process.on("SIGTERM", () => {
server.close(() => {
logger.info('Server closed.');
logger.info("Server closed.");
process.exit(0);
});
});

View File

@ -7,18 +7,16 @@ class BotApiService {
async getAll(): Promise<BotApiResponse> {
const get_url = `${this.BOT_API_URI}/images`;
const response: BotApiResponse = await fetch(get_url)
.then(async res => {
const response: BotApiResponse = (await fetch(get_url).then(async (res) => {
if (!res.ok) {
logger.error(`${res.status}: ${res.statusText}, ${await res.text()}`)
logger.error(`${res.status}: ${res.statusText}, ${await res.text()}`);
throw new Error("Error fetching images");
} else {
return res.json();
}
}) as BotApiResponse;
})) as BotApiResponse;
return response;
}
}
export default new BotApiService();

View File

@ -9,17 +9,23 @@ class GelbooruApiService {
const TAGS = encodeURIComponent(env.GELBOORU_TAGS || "");
const url: string = `https://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=${LIMIT}&json=1&tags=${TAGS}`;
const response: GelbooruApiResponse = await fetch(url)
.then(async res => {
const response: GelbooruApiResponse = (await fetch(url).then(
async (res) => {
if (!res.ok) {
logger.error(`${res.status}: ${res.statusText}, ${await res.text()}`)
logger.error(`${res.status}: ${res.statusText}, ${await res.text()}`);
throw new Error("Error fetching images");
} else {
return res.json();
}
}) as GelbooruApiResponse;
}
)) as GelbooruApiResponse;
return { posts: response.post.map(post => ({ url: post.file_url, tags: post.tags.split(" ") })) };
return {
posts: response.post.map((post) => ({
url: post.file_url,
tags: post.tags.split(" "),
})),
};
}
}

View File

@ -11,23 +11,26 @@ class ImageService {
while (this.postsQueue.length === 0) {
const validPosts = await this.getNewValidImages();
this.postsQueue = validPosts;
logger.info(`Got ${validPosts.length} images from remote`)
logger.info(`Got ${validPosts.length} images from remote`);
}
return this.postsQueue.pop() as Image;
}
private async getNewValidImages(): Promise<Image[]> {
const gelbooruResponse: GelbooruServiceResponse = await GelbooruApiService.get();
const gelbooruResponse: GelbooruServiceResponse =
await GelbooruApiService.get();
const posts = gelbooruResponse.posts;
const botResponse = await BotApiService.getAll();
const imagesUrls = botResponse.images.map(image => image.url);
const imagesUrls = botResponse.images.map((image) => image.url);
const validPosts = Promise.all(posts
.filter(post => !imagesUrls.some(url => url === post.url))
const validPosts = Promise.all(
posts
.filter((post) => !imagesUrls.some((url) => url === post.url))
.map((post): Image => {
return { url: post.url, tags: post.tags };
}));
})
);
return validPosts;
}

View File

@ -1,5 +1,5 @@
import BotImage from "src/types/BotImage";
export interface BotApiResponse {
images: BotImage[]
images: BotImage[];
}

View File

@ -1,7 +1,7 @@
export default interface BotImage {
_id: string
url: string
status: string
tags: string[]
__v: number
_id: string;
url: string;
status: string;
tags: string[];
__v: number;
}

View File

@ -1,42 +1,42 @@
export default interface GelbooruApiResponse {
"@attributes": Attributes
post: Post[]
"@attributes": Attributes;
post: Post[];
}
export interface Attributes {
limit: number
offset: number
count: number
limit: number;
offset: number;
count: number;
}
export interface Post {
id: number
created_at: string
score: number
width: number
height: number
md5: string
directory: string
image: string
rating: string
source: string
change: number
owner: string
creator_id: number
parent_id: number
sample: number
preview_height: number
preview_width: number
tags: string
title: string
has_notes: string
has_comments: string
file_url: string
preview_url: string
sample_url: string
sample_height: number
sample_width: number
status: string
post_locked: number
has_children: string
id: number;
created_at: string;
score: number;
width: number;
height: number;
md5: string;
directory: string;
image: string;
rating: string;
source: string;
change: number;
owner: string;
creator_id: number;
parent_id: number;
sample: number;
preview_height: number;
preview_width: number;
tags: string;
title: string;
has_notes: string;
has_comments: string;
file_url: string;
preview_url: string;
sample_url: string;
sample_height: number;
sample_width: number;
status: string;
post_locked: number;
has_children: string;
}

View File

@ -10,7 +10,7 @@ afterEach(() => {
mock.module("src/services/ImageService", () => ({
default: imageServiceOriginal,
}));
})
});
describe("endpoint returns the correct status codes", () => {
it("should return 200 if successful", async () => {
@ -26,11 +26,11 @@ describe("endpoint returns the correct status codes", () => {
default: {
get: () => {
throw new Error("Controlled error");
}
}
}
},
},
};
});
const res = await request(app).get("/image");
expect(res.status).toBe(500);
});
})
});

View File

@ -19,14 +19,16 @@ afterEach(() => {
default: gelbooruApiServiceOriginal,
}));
mock.module("src/services/BotApiService", () => ({
default: botApiServiceOriginal
default: botApiServiceOriginal,
}));
})
});
describe("endpoint gets a non repeated image", () => {
it("should return an image that is not in the response of the /images endpoint of the bot API", async () => {
const REPEATED_URL = "https://fastly.picsum.photos/id/1/10/20.jpg?hmac=gY6PvUXFacKfYpBpTTVcNLxumpyMmoCamM-J5DOPwNc";
const UNIQUE_URL = "https://fastly.picsum.photos/id/2/10/20.jpg?hmac=zy6lz21CuRIstr9ETx9h5AuoH50s_L2uIEct3dROpY8";
const REPEATED_URL =
"https://fastly.picsum.photos/id/1/10/20.jpg?hmac=gY6PvUXFacKfYpBpTTVcNLxumpyMmoCamM-J5DOPwNc";
const UNIQUE_URL =
"https://fastly.picsum.photos/id/2/10/20.jpg?hmac=zy6lz21CuRIstr9ETx9h5AuoH50s_L2uIEct3dROpY8";
mock.module("src/services/GelbooruApiService", () => {
let alreadyCalled = false;
@ -39,19 +41,25 @@ describe("endpoint gets a non repeated image", () => {
alreadyCalled = true;
return { posts: [{ url: REPEATED_URL, tags: [] }] };
}
}
}
}
},
},
};
});
mock.module("src/services/BotApiService", () => ({
default: {
getAll: (): BotApiResponse => ({
images: [
{ _id: "0", url: REPEATED_URL, status: "consumed", tags: ["pokemon", "computer"], "__v": 0 }
]
})
}
{
_id: "0",
url: REPEATED_URL,
status: "consumed",
tags: ["pokemon", "computer"],
__v: 0,
},
],
}),
},
}));
const image: Image = await ImageService.get();

View File

@ -18,6 +18,6 @@
"types": [
"bun-types" // add Bun global
],
"baseUrl": "./",
"baseUrl": "./"
}
}