diff --git a/TODO.md b/TODO.md index be9a789..b60e289 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,4 @@ - Parametrize bot API url in env variable -- Encode images in base64 -- Parametrize tags \ No newline at end of file +- Encode images in base64 with proper prefix "data:image/png;base64," +- Parametrize tags +- Generalize the ImageService test with faker \ No newline at end of file diff --git a/src/services/ImageService.ts b/src/services/ImageService.ts index 2b8ca37..6b47e37 100644 --- a/src/services/ImageService.ts +++ b/src/services/ImageService.ts @@ -5,7 +5,7 @@ import GelbooruApiService from "./GelbooruApiService"; class ImageService { postsQueue: Image[] = []; - + async get(): Promise { while (this.postsQueue.length === 0) { const validPosts = await this.getNewValidImages(); @@ -21,12 +21,24 @@ class ImageService { const botResponse = await BotApiService.getAll(); const imagesUrls = botResponse.images.map(image => image.url); - const validPosts = posts + const validPosts = Promise.all(posts .filter(post => !imagesUrls.some(url => url === post.url)) - .map(post => ({ url: post.url, tags: post.tags, content: "TODO" })); - + .map(async (post): Promise => { + const imageData = await this.urlToImageData(post.url); + const encodedImage = this.imageToBase64(imageData); + return { url: post.url, tags: post.tags, content: encodedImage }; + })); + return validPosts; } + + private async urlToImageData(url: string): Promise { + return await (await fetch(url)).text(); + } + + private imageToBase64(imageData: string): string { + return Buffer.from(imageData, "binary").toString("base64"); + } } export default new ImageService(); \ No newline at end of file diff --git a/test/ImageService.test.ts b/test/ImageService.test.ts deleted file mode 100644 index 6b9381a..0000000 --- a/test/ImageService.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { describe, expect, it, mock } from "bun:test"; -import Image from "../src/types/Image"; -import ImageService from "../src/services/ImageService"; -import GelbooruApiResponse from "../src/types/GelbooruServiceResponse"; -import { BotApiResponse } from "../src/types/BotApiResponse"; - -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 = "image.com/1"; - const UNIQUE_URL = "image.com/2"; - - mock.module("../src/services/GelbooruApiService", () => { - let alreadyCalled = false; - return { - default: { - get: (): GelbooruApiResponse => { - if (alreadyCalled) { - return { posts: [{ url: UNIQUE_URL, tags: [] }] }; - } else { - 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 } - ] - }) - } - })); - - const image: Image = await ImageService.get(); - expect(image.url).not.toBe(REPEATED_URL); - }) -}) \ No newline at end of file diff --git a/test/ImageService/ImageService.test.ts b/test/ImageService/ImageService.test.ts new file mode 100644 index 0000000..359a131 --- /dev/null +++ b/test/ImageService/ImageService.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it, mock, spyOn } from "bun:test"; +import Image from "../../src/types/Image"; +import ImageService from "../../src/services/ImageService"; +import GelbooruApiResponse from "../../src/types/GelbooruServiceResponse"; +import { BotApiResponse } from "../../src/types/BotApiResponse"; +import fs from "node:fs"; + +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"; + + mock.module("../../src/services/GelbooruApiService", () => { + let alreadyCalled = false; + return { + default: { + get: (): GelbooruApiResponse => { + if (alreadyCalled) { + return { posts: [{ url: UNIQUE_URL, tags: [] }] }; + } else { + 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 } + ] + }) + } + })); + + const image: Image = await ImageService.get(); + expect(image.url).not.toBe(REPEATED_URL); + }); +}); + +describe("imageToBase64 works as expected", () => { + it("should encode image to base64 properly", () => { + const imageData = fs.readFileSync('./test/ImageService/testImage.jpg'); + const imageToBase64Spy = spyOn(ImageService as any, 'imageToBase64'); + + const actualEncoding = imageToBase64Spy.call(ImageService, imageData); + const expectedEncoding = fs.readFileSync('./test/ImageService/testImage.b64', "base64").toString(); + + expect(actualEncoding).toBe(expectedEncoding); + }) +}) \ No newline at end of file diff --git a/test/ImageService/testImage.b64 b/test/ImageService/testImage.b64 new file mode 100644 index 0000000..c559d97 --- /dev/null +++ b/test/ImageService/testImage.b64 @@ -0,0 +1 @@ +/9j/4QDeRXhpZgAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwABAAAAAgAAABMCAwABAAAAAQAAAGmHBAABAAAAZgAAAAAAAABIAAAAAQAAAEgAAAABAAAABwAAkAcABAAAADAyMTABkQcABAAAAAECAwCGkgcAFQAAAMAAAAAAoAcABAAAADAxMDABoAMAAQAAAP//AAACoAQAAQAAAAIAAAADoAQAAQAAAAIAAAAAAAAAQVNDSUkAAABQaWNzdW0gSUQ6IDEwAP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/CABEIAAIAAgMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAABf/EABUBAQEAAAAAAAAAAAAAAAAAAAIE/9oADAMBAAIQAxAAAAGIHP8A/8QAFhAAAwAAAAAAAAAAAAAAAAAAAAMT/9oACAEBAAEFAqsP/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPwF//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPwF//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAIzkf/aAAgBAQAGPwKjaf/EABUQAQEAAAAAAAAAAAAAAAAAAADx/9oACAEBAAE/Ibt//9oADAMBAAIAAwAAABD3/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPxB//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPxB//8QAGBAAAgMAAAAAAAAAAAAAAAAAAAERgfD/2gAIAQEAAT8QUCyWf//Z \ No newline at end of file diff --git a/test/ImageService/testImage.jpg b/test/ImageService/testImage.jpg new file mode 100644 index 0000000..90ec4fa Binary files /dev/null and b/test/ImageService/testImage.jpg differ