mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
11 changed files with 148 additions and 8 deletions
@ -0,0 +1,54 @@ |
|||
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; |
|||
import { |
|||
Controller, |
|||
Get, |
|||
HttpStatus, |
|||
Param, |
|||
Query, |
|||
Res, |
|||
UseInterceptors |
|||
} from '@nestjs/common'; |
|||
import { DataSource } from '@prisma/client'; |
|||
import { Response } from 'express'; |
|||
|
|||
import { LogoService } from './logo.service'; |
|||
|
|||
@Controller('logo') |
|||
export class LogoController { |
|||
public constructor(private readonly logoService: LogoService) {} |
|||
|
|||
@Get(':dataSource/:symbol') |
|||
@UseInterceptors(TransformDataSourceInRequestInterceptor) |
|||
public async getLogoByDataSourceAndSymbol( |
|||
@Param('dataSource') dataSource: DataSource, |
|||
@Param('symbol') symbol: string, |
|||
@Res() response: Response |
|||
) { |
|||
try { |
|||
const buffer = await this.logoService.getLogoByDataSourceAndSymbol({ |
|||
dataSource, |
|||
symbol |
|||
}); |
|||
|
|||
response.contentType('image/png'); |
|||
response.send(buffer); |
|||
} catch { |
|||
response.status(HttpStatus.NOT_FOUND).send(); |
|||
} |
|||
} |
|||
|
|||
@Get() |
|||
public async getLogoByUrl( |
|||
@Query('url') url: string, |
|||
@Res() response: Response |
|||
) { |
|||
try { |
|||
const buffer = await this.logoService.getLogoByUrl(url); |
|||
|
|||
response.contentType('image/png'); |
|||
response.send(buffer); |
|||
} catch { |
|||
response.status(HttpStatus.NOT_FOUND).send(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module'; |
|||
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module'; |
|||
import { Module } from '@nestjs/common'; |
|||
|
|||
import { LogoController } from './logo.controller'; |
|||
import { LogoService } from './logo.service'; |
|||
|
|||
@Module({ |
|||
controllers: [LogoController], |
|||
imports: [ConfigurationModule, SymbolProfileModule], |
|||
providers: [LogoService] |
|||
}) |
|||
export class LogoModule {} |
@ -0,0 +1,55 @@ |
|||
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service'; |
|||
import { UniqueAsset } from '@ghostfolio/common/interfaces'; |
|||
import { HttpException, Injectable } from '@nestjs/common'; |
|||
import { DataSource } from '@prisma/client'; |
|||
import * as bent from 'bent'; |
|||
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; |
|||
|
|||
@Injectable() |
|||
export class LogoService { |
|||
public constructor( |
|||
private readonly symbolProfileService: SymbolProfileService |
|||
) {} |
|||
|
|||
public async getLogoByDataSourceAndSymbol({ |
|||
dataSource, |
|||
symbol |
|||
}: UniqueAsset) { |
|||
if (!DataSource[dataSource]) { |
|||
throw new HttpException( |
|||
getReasonPhrase(StatusCodes.NOT_FOUND), |
|||
StatusCodes.NOT_FOUND |
|||
); |
|||
} |
|||
|
|||
const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([ |
|||
{ dataSource, symbol } |
|||
]); |
|||
|
|||
if (!assetProfile) { |
|||
throw new HttpException( |
|||
getReasonPhrase(StatusCodes.NOT_FOUND), |
|||
StatusCodes.NOT_FOUND |
|||
); |
|||
} |
|||
|
|||
return this.getBuffer(assetProfile.url); |
|||
} |
|||
|
|||
public async getLogoByUrl(aUrl: string) { |
|||
return this.getBuffer(aUrl); |
|||
} |
|||
|
|||
private getBuffer(aUrl: string) { |
|||
const get = bent( |
|||
`https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${aUrl}&size=64`, |
|||
'GET', |
|||
'buffer', |
|||
200, |
|||
{ |
|||
'User-Agent': 'request' |
|||
} |
|||
); |
|||
return get(); |
|||
} |
|||
} |
@ -1,6 +1,7 @@ |
|||
<img |
|||
*ngIf="url" |
|||
src="https://www.google.com/s2/favicons?domain={{ url }}&sz=64" |
|||
*ngIf="src" |
|||
onerror="this.style.display='none'" |
|||
[ngClass]="{ large: size === 'large' }" |
|||
[src]="src" |
|||
[title]="tooltip ? tooltip : ''" |
|||
/> |
|||
|
Loading…
Reference in new issue