mirror of https://github.com/ghostfolio/ghostfolio
				
				
			
							committed by
							
								 GitHub
								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