This repository has been archived by the owner on Aug 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: higlight card upload & storage (#39)
* feat: higlight card upload & storage * feat: added parse int pipe * parseIntPipe * type fixes * feat: check if highlight needs regeneration * lint
- Loading branch information
1 parent
e61f754
commit b6abefa
Showing
6 changed files
with
164 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/social-card/highlight-card/highlight-card.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Controller, Get, Header, HttpStatus, Param, ParseIntPipe, Redirect, Res, StreamableFile } from "@nestjs/common"; | ||
import { | ||
ApiBadRequestResponse, | ||
ApiForbiddenResponse, | ||
ApiNoContentResponse, | ||
ApiNotFoundResponse, | ||
ApiOkResponse, | ||
ApiOperation, ApiResponse, | ||
ApiTags, | ||
} from "@nestjs/swagger"; | ||
import { FastifyReply } from "fastify"; | ||
import { HighlightCardService } from "./highlight-card.service"; | ||
|
||
|
||
@Controller("highlights") | ||
@ApiTags("Highlight social cards") | ||
export class HighlightCardController { | ||
constructor ( | ||
private readonly highlightCardService: HighlightCardService, | ||
) {} | ||
|
||
@Get("/:id") | ||
@ApiOperation({ | ||
operationId: "generateHighlightSocialCard", | ||
summary: "Gets latest cache aware social card link for :id or generates a new one", | ||
}) | ||
@Header("Content-Type", "image/png") | ||
@ApiOkResponse({ type: StreamableFile, description: "Social card image" }) | ||
@ApiNotFoundResponse({ description: "Highlight not found" }) | ||
@ApiForbiddenResponse({ description: "Rate limit exceeded" }) | ||
@ApiBadRequestResponse({ description: "Invalid highlight id" }) | ||
@Redirect() | ||
async generateHighlightSocialCard ( | ||
@Param("id", ParseIntPipe) id: number, | ||
@Res({ passthrough: true }) res: FastifyReply, | ||
): Promise<void> { | ||
const { fileUrl, hasFile, needsUpdate } = await this.highlightCardService.checkRequiresUpdate(id); | ||
|
||
if (hasFile && !needsUpdate) { | ||
return res.status(HttpStatus.FOUND).redirect(fileUrl); | ||
} | ||
|
||
const url = await this.highlightCardService.getHighlightCard(id); | ||
|
||
return res.status(HttpStatus.FOUND).redirect(url); | ||
} | ||
|
||
@Get("/:id/metadata") | ||
@ApiOperation({ | ||
operationId: "getHighlightSocialCardMetadata", | ||
summary: "Gets latest cache aware social card metadata for :id", | ||
}) | ||
@ApiNoContentResponse({ description: "Highlight social card image is up to date", status: HttpStatus.NO_CONTENT }) | ||
@ApiResponse({ description: "Highlight social card image needs regeneration", status: HttpStatus.NOT_MODIFIED }) | ||
@ApiNotFoundResponse({ description: "Highlight social card image not found", status: HttpStatus.NOT_FOUND }) | ||
@ApiBadRequestResponse({ description: "Invalid highlight id", status: HttpStatus.BAD_REQUEST }) | ||
async checkHighlightSocialCard ( | ||
@Param("id", ParseIntPipe) id: number, | ||
@Res({ passthrough: true }) res: FastifyReply, | ||
): Promise<void> { | ||
const { fileUrl, hasFile, needsUpdate, lastModified } = await this.highlightCardService.checkRequiresUpdate(id); | ||
|
||
return res | ||
.headers({ | ||
"x-amz-meta-last-modified": lastModified?.toISOString() ?? "", | ||
"x-amz-meta-location": fileUrl, | ||
}) | ||
.status(hasFile ? needsUpdate ? HttpStatus.NOT_MODIFIED : HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND) | ||
.send(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
export default interface RequiresUpdateMeta { | ||
fileUrl: string, | ||
hasFile: boolean; | ||
needsUpdate: boolean; | ||
lastModified: Date | null, | ||
} |