@@ -3,13 +3,13 @@ import { HttpService } from "@nestjs/axios";
33import { Resvg } from "@resvg/resvg-js" ;
44import { Repository , Language } from "@octokit/graphql-schema" ;
55import fs from "node:fs/promises" ;
6+ import { firstValueFrom } from "rxjs" ;
67
78import { GithubService } from "../../github/github.service" ;
89import { S3FileStorageService } from "../../s3-file-storage/s3-file-storage.service" ;
910import userLangs from "../templates/shared/user-langs" ;
1011import userProfileRepos from "../templates/shared/user-repos" ;
1112import tailwindConfig from "../templates/tailwind.config" ;
12- import { firstValueFrom } from "rxjs" ;
1313import highlightCardTemplate from "../templates/highlight-card.template" ;
1414import { DbUserHighlight } from "../../github/entities/db-user-highlight.entity" ;
1515import { DbReaction } from "../../github/entities/db-reaction.entity" ;
@@ -32,6 +32,7 @@ interface HighlightCardData {
3232@Injectable ( )
3333export class HighlightCardService {
3434 private readonly logger = new Logger ( this . constructor . name ) ;
35+ private fonts : Buffer [ ] = [ ] ;
3536
3637 constructor (
3738 private readonly httpService : HttpService ,
@@ -40,20 +41,20 @@ export class HighlightCardService {
4041 ) { }
4142
4243 private async getHighlightData ( highlightId : number ) : Promise < HighlightCardData > {
43- const highlightReq = await firstValueFrom (
44- this . httpService . get < DbUserHighlight > ( `https://api.opensauced.pizza /v1/user/highlights/${ highlightId } ` ) ,
44+ const highlightReq = firstValueFrom (
45+ this . httpService . get < DbUserHighlight > ( `${ process . env . API_BASE_URL ! } /v1/user/highlights/${ highlightId } ` ) ,
4546 ) ;
46- const { login, updated_at, url, highlight : body } = highlightReq . data ;
4747
48- const reactionsReq = await firstValueFrom (
49- this . httpService . get < DbReaction [ ] > ( `https://api.opensauced.pizza /v1/highlights/${ highlightId } /reactions` ) ,
48+ const reactionsReq = firstValueFrom (
49+ this . httpService . get < DbReaction [ ] > ( `${ process . env . API_BASE_URL ! } /v1/highlights/${ highlightId } /reactions` ) ,
5050 ) ;
51- const reactions = reactionsReq . data . reduce < number > ( ( acc , curr ) => acc + Number ( curr . reaction_count ) , 0 ) ;
5251
52+ const [ highlight , highlightReactions ] = await Promise . all ( [ highlightReq , reactionsReq ] ) ;
53+ const { login, updated_at, url, highlight : body } = highlight . data ;
5354 const [ owner , repoName ] = url . replace ( "https://github.com/" , "" ) . split ( "/" ) ;
5455
55- const user = await this . githubService . getUser ( login ) ;
5656 const repo = await this . githubService . getRepo ( owner , repoName ) ;
57+ const reactions = highlightReactions . data . reduce < number > ( ( acc , curr ) => acc + Number ( curr . reaction_count ) , 0 ) ;
5758
5859 const langList = repo . languages ?. edges ?. flatMap ( edge => {
5960 if ( edge ) {
@@ -68,7 +69,7 @@ export class HighlightCardService {
6869 body,
6970 login,
7071 reactions,
71- avatarUrl : `${ String ( user . avatarUrl ) } & size=150` ,
72+ avatarUrl : `https://github.com/ ${ login } .png? size=150` ,
7273 langs : langList ,
7374 langTotal : repo . languages ?. totalSize ?? 0 ,
7475 repo,
@@ -77,6 +78,17 @@ export class HighlightCardService {
7778 } ;
7879 }
7980
81+ private async getFonts ( ) {
82+ if ( this . fonts . length === 0 ) {
83+ const interArrayBufferReq = fs . readFile ( "node_modules/@fontsource/inter/files/inter-all-400-normal.woff" ) ;
84+ const interArrayBufferMediumReq = fs . readFile ( "node_modules/@fontsource/inter/files/inter-all-500-normal.woff" ) ;
85+
86+ this . fonts = await Promise . all ( [ interArrayBufferReq , interArrayBufferMediumReq ] ) ;
87+ }
88+
89+ return this . fonts ;
90+ }
91+
8092 // public only to be used in local scripts. Not for controller direct use.
8193 async generateCardBuffer ( highlightId : number , highlightData ?: HighlightCardData ) {
8294 const { html } = await import ( "satori-html" ) ;
@@ -90,8 +102,7 @@ export class HighlightCardService {
90102 highlightCardTemplate ( avatarUrl , body , userLangs ( langs , langTotal ) , userProfileRepos ( [ repo ] , 2 ) , reactions ) ,
91103 ) ;
92104
93- const interArrayBuffer = await fs . readFile ( "node_modules/@fontsource/inter/files/inter-all-400-normal.woff" ) ;
94- const interArrayBufferMedium = await fs . readFile ( "node_modules/@fontsource/inter/files/inter-all-500-normal.woff" ) ;
105+ const [ interArrayBuffer , interArrayBufferMedium ] = await this . getFonts ( ) ;
95106
96107 const svg = await satori ( template , {
97108 width : 1200 ,
@@ -133,12 +144,16 @@ export class HighlightCardService {
133144 } ;
134145
135146 if ( hasFile ) {
136- const lastModified = await this . s3FileStorageService . getFileLastModified ( hash ) ;
147+ const lastModifiedReq = this . s3FileStorageService . getFileLastModified ( hash ) ;
148+ const highlightReq = this . getHighlightData ( id ) ;
149+ const metadataReq = this . s3FileStorageService . getFileMeta ( hash ) ;
150+
151+ const [ lastModified , highlight , metadata ] = await Promise . all ( [ lastModifiedReq , highlightReq , metadataReq ] ) ;
137152
138153 returnVal . lastModified = lastModified ;
139154
140- const { updated_at, reactions } = await this . getHighlightData ( id ) ;
141- const metadata = await this . s3FileStorageService . getFileMeta ( hash ) ;
155+ const { updated_at, reactions } = highlight ;
156+
142157 const savedReactions = metadata ?. [ "reactions-count" ] ?? "0" ;
143158
144159 if ( lastModified && lastModified > updated_at && savedReactions === String ( reactions ) ) {
@@ -152,7 +167,7 @@ export class HighlightCardService {
152167 return returnVal ;
153168 }
154169
155- async getHighlightCard ( id : number ) : Promise < string > {
170+ async getHighlightCard ( id : number ) : Promise < Buffer > {
156171 const { remaining } = await this . githubService . rateLimit ( ) ;
157172
158173 if ( remaining < 1000 ) {
@@ -162,16 +177,9 @@ export class HighlightCardService {
162177 const highlightData = await this . getHighlightData ( id ) ;
163178
164179 try {
165- const hash = `highlights/${ String ( id ) } .png` ;
166- const fileUrl = `${ this . s3FileStorageService . getCdnEndpoint ( ) } ${ hash } ` ;
167-
168180 const { png } = await this . generateCardBuffer ( id , highlightData ) ;
169181
170- await this . s3FileStorageService . uploadFile ( png , hash , "image/png" , { "reactions-count" : String ( highlightData . reactions ) } ) ;
171-
172- this . logger . debug ( `Highlight ${ id } did not exist in S3, generated image and uploaded to S3, redirecting` ) ;
173-
174- return fileUrl ;
182+ return png ;
175183 } catch ( e ) {
176184 this . logger . error ( `Error generating highlight card for ${ id } ` , e ) ;
177185
0 commit comments