using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Microsoft.EntityFrameworkCore; using Application.Abstractions.Cache; namespace Application.Features.Config.Get; public sealed class Handler(IAppDbContext db, ICacheService cache) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var cached = await cache.GetAsync(CacheKeys.Config, ct); if (cached is not null) { return cached; } var config = await db.Config.AsNoTracking().OrderByDescending(x => x.ID).FirstOrDefaultAsync(ct); if (config is null) { return null; } var response = new Response { ID = config.ID, Basic = new Response.BasicConfigDto { SiteName = config.Basic.SiteName, SiteURL = config.Basic.SiteURL, RootID = config.Basic.RootID, FromEmail = config.Basic.FromEmail, FromName = config.Basic.FromName, SmtpServer = config.Basic.SmtpServer, SmtpPort = config.Basic.SmtpPort, SmtpEnableSSL = config.Basic.SmtpEnableSSL, SmtpUsername = config.Basic.SmtpUsername, SmtpPassword = config.Basic.SmtpPassword, AdminWhiteIPList = config.Basic.AdminWhiteIPList, FrontWhiteIPList = config.Basic.FrontWhiteIPList, BlockAlertTitle = config.Basic.BlockAlertTitle, BlockAlertContent = config.Basic.BlockAlertContent, IsMaintenance = config.Basic.IsMaintenance, MaintenanceContent = config.Basic.MaintenanceContent, NoteDailySendLimit = config.Basic.NoteDailySendLimit }, Images = new Response.ImagesConfigDto { FaviconPath = config.Images.Favicon, LogoSquarePath = config.Images.LogoSquare, LogoHorizontalPath = config.Images.LogoHorizontal, OgDefaultPath = config.Images.OgDefault, TwitterImagePath = config.Images.TwitterImage, AppleTouchIconPath = config.Images.AppleTouchIcon, AppIcon192Path = config.Images.AppIcon_192, AppIcon512Path = config.Images.AppIcon_512 }, Meta = new Response.MetaConfigDto { Keywords = config.Meta.Keywords, Description = config.Meta.Description, Author = config.Meta.Author, Viewport = config.Meta.Viewport, ApplicationName = config.Meta.ApplicationName, Generator = config.Meta.Generator, Robots = config.Meta.Robots, Adds = config.Meta.Adds }, Company = new Response.CompanyConfigDto { Name = config.Company.Name, RegNo = config.Company.RegNo, Address = config.Company.Address, ZipCode = config.Company.ZipCode, Owner = config.Company.Owner, Tel = config.Company.Tel, Fax = config.Company.Fax, RetailSaleNo = config.Company.RetailSaleNo, AddedSaleNo = config.Company.AddedSaleNo, Hosting = config.Company.Hosting, AdminName = config.Company.AdminName, AdminEmail = config.Company.AdminEmail, SiteUrl = config.Company.SiteUrl, BankCode = config.Company.BankCode, BankOwner = config.Company.BankOwner, BankNumber = config.Company.BankNumber }, Account = new Response.AccountConfigDto { IsRegisterBlock = config.Account.IsRegisterBlock, IsRegisterEmailAuth = config.Account.IsRegisterEmailAuth, PasswordMinLength = config.Account.PasswordMinLength, PasswordUppercaseLength = config.Account.PasswordUppercaseLength, PasswordNumbersLength = config.Account.PasswordNumbersLength, PasswordSpecialcharsLength = config.Account.PasswordSpecialcharsLength, DeniedEmailList = config.Account.DeniedEmailList, DeniedNameList = config.Account.DeniedNameList, ChangeEmailDay = config.Account.ChangeEmailDay, ChangeNameDay = config.Account.ChangeNameDay, ChangeSummaryDay = config.Account.ChangeSummaryDay, ChangeIntroDay = config.Account.ChangeIntroDay, ChangeThumbDay = config.Account.ChangeThumbDay, ChangePasswordDay = config.Account.ChangePasswordDay, IsLoginEmailVerifiedOnly = config.Account.IsLoginEmailVerifiedOnly, MaxLoginTryCount = config.Account.MaxLoginTryCount, MaxLoginTryLimitSecond = config.Account.MaxLoginTryLimitSecond }, EmailTemplate = new Response.EmailTemplateConfigDto { RegisterEmailFormTitle = config.EmailTemplate.RegisterEmailFormTitle, RegisterEmailFormContent = config.EmailTemplate.RegisterEmailFormContent, RegistrationEmailFormTitle = config.EmailTemplate.RegistrationEmailFormTitle, RegistrationEmailFormContent = config.EmailTemplate.RegistrationEmailFormContent, ResetPasswordEmailFormTitle = config.EmailTemplate.ResetPasswordEmailFormTitle, ResetPasswordEmailFormContent = config.EmailTemplate.ResetPasswordEmailFormContent, ChangedPasswordEmailFormTitle = config.EmailTemplate.ChangedPasswordEmailFormTitle, ChangedPasswordEmailFormContent = config.EmailTemplate.ChangedPasswordEmailFormContent, WithdrawEmailFormTitle = config.EmailTemplate.WithdrawEmailFormTitle, WithdrawEmailFormContent = config.EmailTemplate.WithdrawEmailFormContent, WithdrawVerifyEmailFormTitle = config.EmailTemplate.WithdrawVerifyEmailFormTitle, WithdrawVerifyEmailFormContent = config.EmailTemplate.WithdrawVerifyEmailFormContent, EmailVerifyFormTitle = config.EmailTemplate.EmailVerifyFormTitle, EmailVerifyFormContent = config.EmailTemplate.EmailVerifyFormContent, ChangedEmailFormTitle = config.EmailTemplate.ChangedEmailFormTitle, ChangedEmailFormContent = config.EmailTemplate.ChangedEmailFormContent }, External = new Response.ExternalApiConfigDto { YouTubeApiKeyEnc = config.External.YouTubeApiKeyEnc, YouTubeApiName = config.External.YouTubeApiName, GoogleClientId = config.External.GoogleClientId, GoogleClientSecretEnc = config.External.GoogleClientSecretEnc, GoogleAppId = config.External.GoogleAppId, NaverClientId = config.External.NaverClientId, HasNaverClientSecret = !string.IsNullOrEmpty(config.External.NaverClientSecretEnc), HasKakaoRestApiKey = !string.IsNullOrEmpty(config.External.KakaoRestApiKeyEnc), KakaoJavascriptKey = config.External.KakaoJavascriptKey, HasKakaoAdminKey = !string.IsNullOrEmpty(config.External.KakaoAdminKeyEnc), NaverSearchClientId = config.External.NaverSearchClientId, HasNaverSearchClientSecret = !string.IsNullOrEmpty(config.External.NaverSearchClientSecretEnc) }, Toss = new Response.TossConfigDto { TossPayMode = config.External.TossPayMode, HasTestClientKey = !string.IsNullOrEmpty(config.External.TossTestClientKeyEnc), HasTestSecretKey = !string.IsNullOrEmpty(config.External.TossTestSecretKeyEnc), HasLiveClientKey = !string.IsNullOrEmpty(config.External.TossLiveClientKeyEnc), HasLiveSecretKey = !string.IsNullOrEmpty(config.External.TossLiveSecretKeyEnc) }, Attendance = new Response.AttendanceConfigDto { IsEnabled = config.Attendance.IsEnabled, BaseExp = config.Attendance.BaseExp, BasePoint = config.Attendance.BasePoint, UseStreakBonus = config.Attendance.UseStreakBonus, StreakBonusPerDay = config.Attendance.StreakBonusPerDay, StreakBonusPointPerDay = config.Attendance.StreakBonusPointPerDay, StreakBonusMaxDays = config.Attendance.StreakBonusMaxDays, UseRankBonus = config.Attendance.UseRankBonus, RankBonusConfig = config.Attendance.RankBonusConfig }, SignupReward = new Response.SignupRewardConfigDto { Enabled = config.SignupReward.Enabled, CoinAmount = config.SignupReward.CoinAmount, CashAmount = config.SignupReward.CashAmount, ExpAmount = config.SignupReward.ExpAmount }, Reward = new Response.RewardConfigDto { PostExp = config.Reward.PostExp, PostPoint = config.Reward.PostPoint, CommentExp = config.Reward.CommentExp, CommentPoint = config.Reward.CommentPoint, LikeGivenExp = config.Reward.LikeGivenExp, LikeReceivedPoint = config.Reward.LikeReceivedPoint, MinPostLength = config.Reward.MinPostLength, MinCommentLength = config.Reward.MinCommentLength, NewMemberHoldDays = config.Reward.NewMemberHoldDays, PostDailyCount = config.Reward.PostDailyCount, PostDailyExp = config.Reward.PostDailyExp, PostDailyPoint = config.Reward.PostDailyPoint, CommentDailyCount = config.Reward.CommentDailyCount, CommentDailyExp = config.Reward.CommentDailyExp, CommentDailyPoint = config.Reward.CommentDailyPoint, LikeGivenDailyCount = config.Reward.LikeGivenDailyCount, LikeGivenDailyExp = config.Reward.LikeGivenDailyExp, LikeReceivedDailyCount = config.Reward.LikeReceivedDailyCount, LikeReceivedDailyPoint = config.Reward.LikeReceivedDailyPoint, ChatDailyCount = config.Reward.ChatDailyCount, ChatDailyExp = config.Reward.ChatDailyExp, CheerFeePercent = config.Reward.CheerFeePercent, CheerMinAmount = config.Reward.CheerMinAmount, CheerDailyMax = config.Reward.CheerDailyMax }, Paper = new Response.PaperConfigDto { Enabled = config.Paper.Enabled, FeeRateBp = config.Paper.FeeRateBp, TaxRateBp = config.Paper.TaxRateBp, MinDeposit = config.Paper.MinDeposit, MaxHolding = config.Paper.MaxHolding, WithdrawProfitBurnBp = config.Paper.WithdrawProfitBurnBp, OrderMaxPctBp = config.Paper.OrderMaxPctBp, MinFillsForRank = config.Paper.MinFillsForRank }, DataCollection = new Response.DataCollectionConfigDto { HasDataGoKrServiceKey = !string.IsNullOrEmpty(config.DataCollection.DataGoKrServiceKeyEnc), HasKrxApiKey = !string.IsNullOrEmpty(config.DataCollection.KrxApiKeyEnc), HasOpenDartApiKey = !string.IsNullOrEmpty(config.DataCollection.OpenDartApiKeyEnc), HasKoreaEximExchangeKey = !string.IsNullOrEmpty(config.DataCollection.KoreaEximExchangeKeyEnc), HasKoreaEximLoanRateKey = !string.IsNullOrEmpty(config.DataCollection.KoreaEximLoanRateKeyEnc), HasKoreaEximIntlRateKey = !string.IsNullOrEmpty(config.DataCollection.KoreaEximIntlRateKeyEnc), HasSeibroApiKey = !string.IsNullOrEmpty(config.DataCollection.SeibroApiKeyEnc), HasKosisApiKey = !string.IsNullOrEmpty(config.DataCollection.KosisApiKeyEnc), StockDataMasterSync = config.DataCollection.StockDataMasterSync, StockDataDailyPriceSync = config.DataCollection.StockDataDailyPriceSync, KrxIndexSync = config.DataCollection.KrxIndexSync, KrxBondIndexSync = config.DataCollection.KrxBondIndexSync, KrxStockSync = config.DataCollection.KrxStockSync, KrxEtpSync = config.DataCollection.KrxEtpSync, KrxWarrantSync = config.DataCollection.KrxWarrantSync, KrxBondSync = config.DataCollection.KrxBondSync, KrxDerivativeSync = config.DataCollection.KrxDerivativeSync, KrxCommoditySync = config.DataCollection.KrxCommoditySync, KrxEsgSync = config.DataCollection.KrxEsgSync, OpenDartDisclosureSync = config.DataCollection.OpenDartDisclosureSync, KoreaEximMacroSync = config.DataCollection.KoreaEximMacroSync, KosisSync = config.DataCollection.KosisSync, WorldIndexEnabled = config.DataCollection.WorldIndexEnabled, MarketQuoteEnabled = config.DataCollection.MarketQuoteEnabled, SeibroIssuerSync = config.DataCollection.SeibroIssuerSync, SeibroDividendSync = config.DataCollection.SeibroDividendSync, SeibroSupplySync = config.DataCollection.SeibroSupplySync, SeibroCorpActionSync = config.DataCollection.SeibroCorpActionSync, SeibroBondSync = config.DataCollection.SeibroBondSync, SeibroDerivSync = config.DataCollection.SeibroDerivSync, SeibroForeignSync = config.DataCollection.SeibroForeignSync } }; await cache.SetAsync(CacheKeys.Config, response, ct); return response; } }