Browse Source

Bugfix/fix data source of fear and greed index (#663)

* Encode data source

* Update changelog
pull/664/head
Thomas Kaul 3 years ago
committed by GitHub
parent
commit
161cb82820
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 6
      apps/api/src/app/info/info.service.ts
  3. 13
      apps/api/src/interceptors/transform-data-source-in-request.interceptor.ts
  4. 18
      apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts
  5. 7
      apps/client/src/app/components/home-market/home-market.component.ts
  6. 2
      apps/client/src/app/services/data.service.ts
  7. 9
      libs/common/src/lib/helper.ts
  8. 1
      libs/common/src/lib/interfaces/info-item.interface.ts

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
-Fixed the data source of the _Fear & Greed Index_ (market mood)
## 1.109.0 - 01.02.2022 ## 1.109.0 - 01.02.2022
### Added ### Added

6
apps/api/src/app/info/info.service.ts

@ -11,12 +11,14 @@ import {
PROPERTY_STRIPE_CONFIG, PROPERTY_STRIPE_CONFIG,
PROPERTY_SYSTEM_MESSAGE PROPERTY_SYSTEM_MESSAGE
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { encodeDataSource } from '@ghostfolio/common/helper';
import { InfoItem } from '@ghostfolio/common/interfaces'; import { InfoItem } from '@ghostfolio/common/interfaces';
import { Statistics } from '@ghostfolio/common/interfaces/statistics.interface'; import { Statistics } from '@ghostfolio/common/interfaces/statistics.interface';
import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface'; import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface';
import { permissions } from '@ghostfolio/common/permissions'; import { permissions } from '@ghostfolio/common/permissions';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { DataSource } from '@prisma/client';
import * as bent from 'bent'; import * as bent from 'bent';
import { subDays } from 'date-fns'; import { subDays } from 'date-fns';
@ -49,6 +51,10 @@ export class InfoService {
globalPermissions.push(permissions.enableBlog); globalPermissions.push(permissions.enableBlog);
} }
if (this.configurationService.get('ENABLE_FEATURE_FEAR_AND_GREED_INDEX')) {
info.fearAndGreedDataSource = encodeDataSource(DataSource.RAKUTEN);
}
if (this.configurationService.get('ENABLE_FEATURE_IMPORT')) { if (this.configurationService.get('ENABLE_FEATURE_IMPORT')) {
globalPermissions.push(permissions.enableImport); globalPermissions.push(permissions.enableImport);
} }

13
apps/api/src/interceptors/transform-data-source-in-request.interceptor.ts

@ -1,3 +1,4 @@
import { decodeDataSource } from '@ghostfolio/common/helper';
import { import {
CallHandler, CallHandler,
ExecutionContext, ExecutionContext,
@ -24,22 +25,14 @@ export class TransformDataSourceInRequestInterceptor<T>
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') === true) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') === true) {
if (request.body.dataSource) { if (request.body.dataSource) {
request.body.dataSource = this.decodeDataSource( request.body.dataSource = decodeDataSource(request.body.dataSource);
request.body.dataSource
);
} }
if (request.params.dataSource) { if (request.params.dataSource) {
request.params.dataSource = this.decodeDataSource( request.params.dataSource = decodeDataSource(request.params.dataSource);
request.params.dataSource
);
} }
} }
return next.handle(); return next.handle();
} }
private decodeDataSource(encodeDataSource: string) {
return Buffer.from(encodeDataSource, 'hex').toString();
}
} }

18
apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts

@ -1,10 +1,10 @@
import { encodeDataSource } from '@ghostfolio/common/helper';
import { import {
CallHandler, CallHandler,
ExecutionContext, ExecutionContext,
Injectable, Injectable,
NestInterceptor NestInterceptor
} from '@nestjs/common'; } from '@nestjs/common';
import { DataSource } from '@prisma/client';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ConfigurationService } from '../services/configuration.service'; import { ConfigurationService } from '../services/configuration.service';
@ -28,22 +28,22 @@ export class TransformDataSourceInResponseInterceptor<T>
) { ) {
if (data.activities) { if (data.activities) {
data.activities.map((activity) => { data.activities.map((activity) => {
activity.SymbolProfile.dataSource = this.encodeDataSource( activity.SymbolProfile.dataSource = encodeDataSource(
activity.SymbolProfile.dataSource activity.SymbolProfile.dataSource
); );
activity.dataSource = this.encodeDataSource(activity.dataSource); activity.dataSource = encodeDataSource(activity.dataSource);
return activity; return activity;
}); });
} }
if (data.dataSource) { if (data.dataSource) {
data.dataSource = this.encodeDataSource(data.dataSource); data.dataSource = encodeDataSource(data.dataSource);
} }
if (data.holdings) { if (data.holdings) {
for (const symbol of Object.keys(data.holdings)) { for (const symbol of Object.keys(data.holdings)) {
if (data.holdings[symbol].dataSource) { if (data.holdings[symbol].dataSource) {
data.holdings[symbol].dataSource = this.encodeDataSource( data.holdings[symbol].dataSource = encodeDataSource(
data.holdings[symbol].dataSource data.holdings[symbol].dataSource
); );
} }
@ -52,14 +52,14 @@ export class TransformDataSourceInResponseInterceptor<T>
if (data.items) { if (data.items) {
data.items.map((item) => { data.items.map((item) => {
item.dataSource = this.encodeDataSource(item.dataSource); item.dataSource = encodeDataSource(item.dataSource);
return item; return item;
}); });
} }
if (data.positions) { if (data.positions) {
data.positions.map((position) => { data.positions.map((position) => {
position.dataSource = this.encodeDataSource(position.dataSource); position.dataSource = encodeDataSource(position.dataSource);
return position; return position;
}); });
} }
@ -69,8 +69,4 @@ export class TransformDataSourceInResponseInterceptor<T>
}) })
); );
} }
private encodeDataSource(aDataSource: DataSource) {
return Buffer.from(aDataSource, 'utf-8').toString('hex');
}
} }

7
apps/client/src/app/components/home-market/home-market.component.ts

@ -4,9 +4,8 @@ import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config';
import { resetHours } from '@ghostfolio/common/helper'; import { resetHours } from '@ghostfolio/common/helper';
import { User } from '@ghostfolio/common/interfaces'; import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { DataSource } from '@prisma/client';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
@ -19,6 +18,7 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
public fearAndGreedIndex: number; public fearAndGreedIndex: number;
public hasPermissionToAccessFearAndGreedIndex: boolean; public hasPermissionToAccessFearAndGreedIndex: boolean;
public historicalData: HistoricalDataItem[]; public historicalData: HistoricalDataItem[];
public info: InfoItem;
public isLoading = true; public isLoading = true;
public readonly numberOfDays = 90; public readonly numberOfDays = 90;
public user: User; public user: User;
@ -33,6 +33,7 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
private dataService: DataService, private dataService: DataService,
private userService: UserService private userService: UserService
) { ) {
this.info = this.dataService.fetchInfo();
this.isLoading = true; this.isLoading = true;
this.userService.stateChanged this.userService.stateChanged
@ -49,7 +50,7 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
if (this.hasPermissionToAccessFearAndGreedIndex) { if (this.hasPermissionToAccessFearAndGreedIndex) {
this.dataService this.dataService
.fetchSymbolItem({ .fetchSymbolItem({
dataSource: DataSource.RAKUTEN, dataSource: this.info.fearAndGreedDataSource,
includeHistoricalData: this.numberOfDays, includeHistoricalData: this.numberOfDays,
symbol: ghostfolioFearAndGreedIndexSymbol symbol: ghostfolioFearAndGreedIndexSymbol
}) })

2
apps/client/src/app/services/data.service.ts

@ -141,7 +141,7 @@ export class DataService {
includeHistoricalData, includeHistoricalData,
symbol symbol
}: { }: {
dataSource: DataSource; dataSource: DataSource | string;
includeHistoricalData?: number; includeHistoricalData?: number;
symbol: string; symbol: string;
}) { }) {

9
libs/common/src/lib/helper.ts

@ -1,4 +1,5 @@
import * as currencies from '@dinero.js/currencies'; import * as currencies from '@dinero.js/currencies';
import { DataSource } from '@prisma/client';
import { getDate, getMonth, getYear, parse, subDays } from 'date-fns'; import { getDate, getMonth, getYear, parse, subDays } from 'date-fns';
import { ghostfolioScraperApiSymbolPrefix } from './config'; import { ghostfolioScraperApiSymbolPrefix } from './config';
@ -7,6 +8,14 @@ export function capitalize(aString: string) {
return aString.charAt(0).toUpperCase() + aString.slice(1).toLowerCase(); return aString.charAt(0).toUpperCase() + aString.slice(1).toLowerCase();
} }
export function decodeDataSource(encodedDataSource: string) {
return Buffer.from(encodedDataSource, 'hex').toString();
}
export function encodeDataSource(aDataSource: DataSource) {
return Buffer.from(aDataSource, 'utf-8').toString('hex');
}
export function getBackgroundColor() { export function getBackgroundColor() {
return getCssVariable( return getCssVariable(
window.matchMedia('(prefers-color-scheme: dark)').matches window.matchMedia('(prefers-color-scheme: dark)').matches

1
libs/common/src/lib/interfaces/info-item.interface.ts

@ -4,6 +4,7 @@ import { Subscription } from './subscription.interface';
export interface InfoItem { export interface InfoItem {
currencies: string[]; currencies: string[];
demoAuthToken: string; demoAuthToken: string;
fearAndGreedDataSource?: string;
globalPermissions: string[]; globalPermissions: string[];
isReadOnlyMode?: boolean; isReadOnlyMode?: boolean;
lastDataGathering?: Date; lastDataGathering?: Date;

Loading…
Cancel
Save