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 |
<img |
||||
*ngIf="url" |
*ngIf="src" |
||||
src="https://www.google.com/s2/favicons?domain={{ url }}&sz=64" |
onerror="this.style.display='none'" |
||||
[ngClass]="{ large: size === 'large' }" |
[ngClass]="{ large: size === 'large' }" |
||||
|
[src]="src" |
||||
[title]="tooltip ? tooltip : ''" |
[title]="tooltip ? tooltip : ''" |
||||
/> |
/> |
||||
|
Loading…
Reference in new issue