feat(core): update DTOs, Trade Republic client, Yahoo scrapers, and dynamic settings
This commit is contained in:
@@ -1,107 +0,0 @@
|
||||
using FinlyticCore.Dtos.Assets;
|
||||
using FinlyticCore.Entities.Assets;
|
||||
|
||||
namespace FinlyticCore.Util;
|
||||
|
||||
public static class AssetMapper
|
||||
{
|
||||
|
||||
public static AssetDto ToDto(this AssetEntity entity)
|
||||
{
|
||||
var dtoTags = entity.Tags.Select(t => new TagDto
|
||||
{
|
||||
Id = t.Id,
|
||||
Name = t.Name,
|
||||
Type = t.Type
|
||||
}).ToList();
|
||||
|
||||
return entity switch
|
||||
{
|
||||
StockEntity stock => new StockDto
|
||||
{
|
||||
Isin = stock.Isin,
|
||||
Name = stock.Name,
|
||||
Type = stock.Type,
|
||||
InstrumentCategory = stock.InstrumentCategory,
|
||||
HasCfd = stock.HasCfd,
|
||||
ImageId = stock.ImageId,
|
||||
LastUpdatedAt = stock.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
DerivativeProductCategories = stock.DerivativeProductCategories
|
||||
},
|
||||
EtfEntity etf => new EtfDto
|
||||
{
|
||||
Isin = etf.Isin,
|
||||
Name = etf.Name,
|
||||
Type = etf.Type,
|
||||
InstrumentCategory = etf.InstrumentCategory,
|
||||
HasCfd = etf.HasCfd,
|
||||
ImageId = etf.ImageId,
|
||||
LastUpdatedAt = etf.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
DerivativeProductCategories = etf.DerivativeProductCategories,
|
||||
EtfDescription = etf.EtfDescription,
|
||||
MappedEtfIndexName = etf.MappedEtfIndexName,
|
||||
Subtitle = etf.Subtitle,
|
||||
SearchSubtitle = etf.SearchSubtitle
|
||||
},
|
||||
CryptoEntity crypto => new CryptoDto
|
||||
{
|
||||
Isin = crypto.Isin,
|
||||
Name = crypto.Name,
|
||||
Type = crypto.Type,
|
||||
InstrumentCategory = crypto.InstrumentCategory,
|
||||
HasCfd = crypto.HasCfd,
|
||||
ImageId = crypto.ImageId,
|
||||
LastUpdatedAt = crypto.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
Subtitle = crypto.Subtitle,
|
||||
SearchSubtitle = crypto.SearchSubtitle
|
||||
},
|
||||
BondEntity bond => new BondDto
|
||||
{
|
||||
Isin = bond.Isin,
|
||||
Name = bond.Name,
|
||||
Type = bond.Type,
|
||||
InstrumentCategory = bond.InstrumentCategory,
|
||||
HasCfd = bond.HasCfd,
|
||||
ImageId = bond.ImageId,
|
||||
LastUpdatedAt = bond.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
BondIssuerName = bond.BondIssuerName,
|
||||
SearchSubtitle = bond.SearchSubtitle
|
||||
},
|
||||
DerivativeEntity deriv => new DerivativeDto
|
||||
{
|
||||
Isin = deriv.Isin,
|
||||
Name = deriv.Name,
|
||||
Type = deriv.Type,
|
||||
InstrumentCategory = deriv.InstrumentCategory,
|
||||
HasCfd = deriv.HasCfd,
|
||||
ImageId = deriv.ImageId,
|
||||
LastUpdatedAt = deriv.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
DerivativeProductCategories = deriv.DerivativeProductCategories,
|
||||
UnderlyingIsin = deriv.UnderlyingIsin
|
||||
},
|
||||
SyntheticEntity synth => new SyntheticDto
|
||||
{
|
||||
Isin = synth.Isin,
|
||||
Name = synth.Name,
|
||||
Type = synth.Type,
|
||||
InstrumentCategory = synth.InstrumentCategory,
|
||||
HasCfd = synth.HasCfd,
|
||||
ImageId = synth.ImageId,
|
||||
LastUpdatedAt = synth.LastUpdatedAt,
|
||||
Tags = dtoTags,
|
||||
DerivativeProductCategories = synth.DerivativeProductCategories
|
||||
},
|
||||
_ => throw new NotSupportedException($"Mapping for type {entity.GetType().Name} is not supported.")
|
||||
};
|
||||
}
|
||||
|
||||
public static List<AssetDto> ToDtoList(this IEnumerable<AssetEntity> entities)
|
||||
{
|
||||
return entities.Select(e => e.ToDto()).ToList();
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ namespace FinlyticCore.Util;
|
||||
[JsonSerializable(typeof(FilteredAssetPayload))]
|
||||
[JsonSerializable(typeof(AssetFundamentalsDto))]
|
||||
[JsonSerializable(typeof(List<AssetFundamentalsDto>))]
|
||||
[JsonSerializable(typeof(TickerInfoDto))]
|
||||
[JsonSerializable(typeof(List<TickerInfoDto>))]
|
||||
[JsonSerializable(typeof(CorporateEventDto))]
|
||||
[JsonSerializable(typeof(List<CorporateEventDto>))]
|
||||
[JsonSerializable(typeof(CalendarEventResponseDto))]
|
||||
@@ -94,12 +96,18 @@ namespace FinlyticCore.Util;
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.Assets.GetValidAssetRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.Assets.SearchAssetsRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.Assets.GetDiscoveryAssetsRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.TradeRepublic.TradeRepublicTickerResponse))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.TradeRepublic.TradeRepublicTickerRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.TradeRepublic.TradeRepublicConnectRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.TradeRepublic.TradeRepublicSearchRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.TradeRepublic.TradeRepublicAssetResponse))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Models.Assets.GetDerivativesRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicTickerResponse))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicTickerRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicConnectRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicSearchRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicAssetResponse))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicDerivativesRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicDerivativesResponse))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicStockDetailsRequest))]
|
||||
[JsonSerializable(typeof(FinlyticCore.Dtos.TradeRepublic.TradeRepublicStockDetailsResponse))]
|
||||
[JsonSerializable(typeof(YahooValueDto))]
|
||||
[JsonSerializable(typeof(YahooQuoteTypeDto))]
|
||||
[JsonSerializable(typeof(YahooQuoteSummaryResponseDto))]
|
||||
[JsonSerializable(typeof(YahooQuoteSummaryResultDto))]
|
||||
[JsonSerializable(typeof(YahooQuoteSummaryModulesDto))]
|
||||
|
||||
@@ -242,37 +242,42 @@ public abstract class ManagedMqttClient : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleIncomingMessageAsync(MqttApplicationMessageReceivedEventArgs e)
|
||||
private Task HandleIncomingMessageAsync(MqttApplicationMessageReceivedEventArgs e)
|
||||
{
|
||||
try
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var topic = e.ApplicationMessage.Topic;
|
||||
var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
||||
_logger.LogInformation("MQTT message received on topic '{Topic}', length={Length}", topic, payload?.Length ?? 0);
|
||||
|
||||
// Intercept message if it belongs to the RPC response convention
|
||||
if (topic.StartsWith("services/response/"))
|
||||
try
|
||||
{
|
||||
var lastSlashIndex = topic.LastIndexOf('/');
|
||||
if (lastSlashIndex != -1)
|
||||
{
|
||||
string correlationId = topic[(lastSlashIndex + 1)..];
|
||||
var topic = e.ApplicationMessage.Topic;
|
||||
var payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
||||
_logger.LogInformation("MQTT message received on topic '{Topic}', length={Length}", topic, payload?.Length ?? 0);
|
||||
|
||||
if (_pendingRequests.TryRemove(correlationId, out var tcs))
|
||||
// Intercept message if it belongs to the RPC response convention
|
||||
if (topic.StartsWith("services/response/"))
|
||||
{
|
||||
var lastSlashIndex = topic.LastIndexOf('/');
|
||||
if (lastSlashIndex != -1)
|
||||
{
|
||||
tcs.SetResult(payload);
|
||||
return; // Sinks the message, avoiding triggering OnMessageReceivedAsync for active RPC handles
|
||||
string correlationId = topic[(lastSlashIndex + 1)..];
|
||||
|
||||
if (_pendingRequests.TryRemove(correlationId, out var tcs))
|
||||
{
|
||||
tcs.SetResult(payload ?? string.Empty);
|
||||
return; // Sinks the message, avoiding triggering OnMessageReceivedAsync for active RPC handles
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regular Pub/Sub message propagation
|
||||
await OnMessageReceivedAsync(topic, payload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnError(ex);
|
||||
}
|
||||
// Regular Pub/Sub message propagation
|
||||
await OnMessageReceivedAsync(topic, payload ?? string.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnError(ex);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task HandleDisconnectAsync(MqttClientDisconnectedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user