| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- namespace Domain.Entities.Common;
- public sealed class Config
- {
- public int ID { get; private set; }
- public DateTime LastUpdatedAt { get; private set; } = DateTime.UtcNow;
- public byte[] RowVersion { get; private set; } = [];
- public BasicConfig Basic { get; private set; } = new();
- public ImagesConfig Images { get; private set; } = new();
- public MetaConfig Meta { get; private set; } = new();
- public CompanyConfig Company { get; private set; } = new();
- public AccountConfig Account { get; private set; } = new();
- public EmailTemplateConfig EmailTemplate { get; private set; } = new();
- public ExternalApiConfig External { get; private set; } = new();
- public CryptoConfig Crypto { get; private set; } = new();
- public AttendanceConfig Attendance { get; private set; } = new();
- public SignupRewardConfig SignupReward { get; private set; } = new();
- public RewardConfig Reward { get; private set; } = new();
- public ChatExpConfig ChatExp { get; private set; } = new();
- public PaperConfig Paper { get; private set; } = new();
- public DataCollectionConfig DataCollection { get; private set; } = new();
- private Config() { }
- public static Config Create()
- {
- return new();
- }
- public void Update(
- BasicConfig basic,
- ImagesConfig images,
- MetaConfig meta,
- CompanyConfig company,
- AccountConfig account,
- EmailTemplateConfig emailTemplate,
- ExternalApiConfig external,
- CryptoConfig crypto,
- AttendanceConfig attendance,
- SignupRewardConfig signupReward
- ) {
- Basic = basic ?? throw new ArgumentNullException(nameof(basic));
- Images = images ?? throw new ArgumentNullException(nameof(images));
- Meta = meta ?? throw new ArgumentNullException(nameof(meta));
- Company = company ?? throw new ArgumentNullException(nameof(company));
- Account = account ?? throw new ArgumentNullException(nameof(account));
- EmailTemplate = emailTemplate ?? throw new ArgumentNullException(nameof(emailTemplate));
- External = external ?? throw new ArgumentNullException(nameof(external));
- Crypto = crypto ?? throw new ArgumentNullException(nameof(crypto));
- Attendance = attendance ?? throw new ArgumentNullException(nameof(attendance));
- SignupReward = signupReward ?? throw new ArgumentNullException(nameof(signupReward));
- LastUpdatedAt = DateTime.UtcNow;
- }
- public void UpdateChatExp(ChatExpConfig chatExp)
- {
- ChatExp = chatExp ?? throw new ArgumentNullException(nameof(chatExp));
- LastUpdatedAt = DateTime.UtcNow;
- }
- public void UpdateReward(RewardConfig reward)
- {
- Reward = reward ?? throw new ArgumentNullException(nameof(reward));
- LastUpdatedAt = DateTime.UtcNow;
- }
- public void UpdatePaper(PaperConfig paper)
- {
- Paper = paper ?? throw new ArgumentNullException(nameof(paper));
- LastUpdatedAt = DateTime.UtcNow;
- }
- public void UpdateDataCollection(DataCollectionConfig dataCollection)
- {
- DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection));
- LastUpdatedAt = DateTime.UtcNow;
- }
- }
- #region Owned Groups
- // ==================================================
- // 기본 정보 (Basic)
- // ==================================================
- public sealed class BasicConfig
- {
- public string? SiteName { get; set; }
- public string? SiteURL { get; set; }
- public string? RootID { get; set; }
- public string? FromEmail { get; set; }
- public string? FromName { get; set; }
- public string? SmtpServer { get; set; }
- public int? SmtpPort { get; set; }
- public bool SmtpEnableSSL { get; set; }
- public string? SmtpUsername { get; set; }
- public string? SmtpPassword { get; set; }
- public string? AdminWhiteIPList { get; set; }
- public string? FrontWhiteIPList { get; set; }
- public string? BlockAlertTitle { get; set; }
- public string? BlockAlertContent { get; set; }
- public bool IsMaintenance { get; set; } = false;
- public string? MaintenanceContent { get; set; }
- /// <summary>쪽지 일일 발송 제한 (사용자 1인당 / 시스템 쪽지 제외). 0 = 발송 차단</summary>
- public int NoteDailySendLimit { get; set; } = 3;
- }
- // ==================================================
- // 기본 이미지 (Images)
- // ==================================================
- public sealed class ImagesConfig
- {
- public string? Favicon { get; set; }
- public string? LogoSquare { get; set; }
- public string? LogoHorizontal { get; set; }
- public string? OgDefault { get; set; }
- public string? TwitterImage { get; set; }
- public string? AppleTouchIcon { get; set; }
- public string? AppIcon_192 { get; set; }
- public string? AppIcon_512 { get; set; }
- }
- // ==================================================
- // 메타 태그 (Meta)
- // ==================================================
- public sealed class MetaConfig
- {
- public string? Keywords { get; set; }
- public string? Description { get; set; }
- public string? Author { get; set; }
- public string? Viewport { get; set; }
- public string? ApplicationName { get; set; }
- public string? Generator { get; set; }
- public string? Robots { get; set; }
- public string? Adds { get; set; }
- }
- // ==================================================
- // 회사 정보 (Company)
- // ==================================================
- public sealed class CompanyConfig
- {
- public string? Name { get; set; }
- public string? RegNo { get; set; }
- public string? Address { get; set; }
- public string? ZipCode { get; set; }
- public string? Owner { get; set; }
- public string? Tel { get; set; }
- public string? Fax { get; set; }
- public string? RetailSaleNo { get; set; }
- public string? AddedSaleNo { get; set; }
- public string? Hosting { get; set; }
- public string? AdminName { get; set; }
- public string? AdminEmail { get; set; }
- public string? SiteUrl { get; set; }
- public string? BankCode { get; set; }
- public string? BankOwner { get; set; }
- public string? BankNumber { get; set; }
- }
- // ==================================================
- // 회원가입 설정 (Account)
- // ==================================================
- public sealed class AccountConfig
- {
- // 회원 가입 시
- public bool IsRegisterBlock { get; set; } = false;
- public bool IsRegisterEmailAuth { get; set; } = false;
- public ushort? PasswordMinLength { get; set; }
- public ushort? PasswordUppercaseLength { get; set; }
- public ushort? PasswordNumbersLength { get; set; }
- public ushort? PasswordSpecialcharsLength { get; set; }
- public string? DeniedEmailList { get; set; }
- public string? DeniedNameList { get; set; }
- // 회원 수정 시 — 프로필(닉네임·한마디·이미지) 기본 90일 쿨다운 (변경권 아이템으로 우회 — Wave 3 P3)
- public ushort? ChangeEmailDay { get; set; }
- public ushort? ChangeNameDay { get; set; } = 90;
- public ushort? ChangeSummaryDay { get; set; }
- public ushort? ChangeIntroDay { get; set; } = 90;
- public ushort? ChangeThumbDay { get; set; } = 90;
- public ushort? ChangePasswordDay { get; set; }
- // 로그인 시
- public bool IsLoginEmailVerifiedOnly { get; set; } = false;
- public ushort? MaxLoginTryCount { get; set; }
- public ushort? MaxLoginTryLimitSecond { get; set; }
- }
- // ==================================================
- // 알림 발송 양식 - 이메일 (EmailTemplate)
- // ==================================================
- public sealed class EmailTemplateConfig
- {
- public string? RegisterEmailFormTitle { get; set; }
- public string? RegisterEmailFormContent { get; set; }
- public string? RegistrationEmailFormTitle { get; set; }
- public string? RegistrationEmailFormContent { get; set; }
- public string? ResetPasswordEmailFormTitle { get; set; }
- public string? ResetPasswordEmailFormContent { get; set; }
- public string? ChangedPasswordEmailFormTitle { get; set; }
- public string? ChangedPasswordEmailFormContent { get; set; }
- public string? WithdrawEmailFormTitle { get; set; }
- public string? WithdrawEmailFormContent { get; set; }
- public string? WithdrawVerifyEmailFormTitle { get; set; }
- public string? WithdrawVerifyEmailFormContent { get; set; }
- public string? EmailVerifyFormTitle { get; set; }
- public string? EmailVerifyFormContent { get; set; }
- public string? ChangedEmailFormTitle { get; set; }
- public string? ChangedEmailFormContent { get; set; }
- }
- // ==================================================
- // 외부 API 설정 (External)
- // ==================================================
- public sealed class ExternalApiConfig
- {
- /** YouTube **/
- public string? YouTubeApiKeyEnc { get; set; }
- public string? YouTubeApiName { get; set; }
- /** 구글 **/
- public string? GoogleClientId { get; set; }
- public string? GoogleClientSecretEnc { get; set; }
- public string? GoogleAppId { get; set; }
- /** 토스페이먼츠 **/
- /// <summary>Toss 결제 환경 (test / live)</summary>
- public string? TossPayMode { get; set; }
- /// <summary>Toss Test Client Key (암호화 저장 권장)</summary>
- public string? TossTestClientKeyEnc { get; set; }
- /// <summary>Toss Test Secret Key (암호화 저장 권장)</summary>
- public string? TossTestSecretKeyEnc { get; set; }
- /// <summary>Toss Live Client Key (암호화 저장 권장)</summary>
- public string? TossLiveClientKeyEnc { get; set; }
- /// <summary>Toss Live Secret Key (암호화 저장 권장)</summary>
- public string? TossLiveSecretKeyEnc { get; set; }
- /** 소셜 로그인 on/off (Admin /Config/External 체크박스). 키가 있어도 false 면 해당 로그인 비활성 **/
- public bool NaverLoginEnabled { get; set; } = true;
- public bool KakaoLoginEnabled { get; set; } = true;
- public bool GoogleLoginEnabled { get; set; } = true;
- /** 네이버 로그인 **/
- public string? NaverClientId { get; set; }
- public string? NaverClientSecretEnc { get; set; }
- /** 카카오 로그인 (ClientId = REST API 키) **/
- public string? KakaoRestApiKeyEnc { get; set; }
- public string? KakaoJavascriptKey { get; set; }
- public string? KakaoAdminKeyEnc { get; set; }
- /** 네이버 검색(뉴스) API **/
- public string? NaverSearchClientId { get; set; }
- public string? NaverSearchClientSecretEnc { get; set; }
- }
- // ==================================================
- // 코인/시세 설정 (Crypto)
- // ==================================================
- public sealed class CryptoConfig
- {
- public int TickerRefreshSeconds { get; set; } = 5;
- public decimal SurgeThreshold { get; set; } = 5.0m;
- public decimal PlungeThreshold { get; set; } = -5.0m;
- public int MainPageCoinCount { get; set; } = 10;
- }
- // ==================================================
- // 채팅 경험치/리더보드 설정 (ChatExp)
- // 관리자: /Channel/Exp 페이지에서 편집
- // ==================================================
- public sealed class ChatExpConfig
- {
- /// <summary>채팅 1건당 지급 XP</summary>
- public int ChatXpPerMessage { get; set; } = 1;
- /// <summary>후원 N POINT당 1 XP (기본 1000 = 1,000원당 1XP)</summary>
- public int DonationXpPerAmount { get; set; } = 1000;
- /// <summary>방송 세션당 채팅 XP 상한 (후원 XP는 무제한)</summary>
- public int ChatXpSessionLimit { get; set; } = 50;
- /// <summary>XP 적립 최소 글자수</summary>
- public int MinContentLength { get; set; } = 2;
- /// <summary>채팅 쿨다운(초) — 기존 RateLimit 재정의</summary>
- public int RateLimitSec { get; set; } = 2;
- /// <summary>리더보드 표시 인원 (Top N)</summary>
- public int LeaderboardSize { get; set; } = 50;
- /// <summary>크라운 뱃지 부여 Top N</summary>
- public int CrownTopN { get; set; } = 3;
- /// <summary>watch 페이지에서 리더보드 기능 노출</summary>
- public bool UxShowLeaderboard { get; set; } = true;
- /// <summary>watch 페이지 채팅창 상단에 "내 XP" 뱃지 노출</summary>
- public bool UxShowMyXpBadge { get; set; } = true;
- }
- // ==================================================
- // 출석 설정 (Attendance)
- // ==================================================
- public sealed class AttendanceConfig
- {
- /// <summary>출석 기능 활성화</summary>
- public bool IsEnabled { get; set; } = false;
- /// <summary>기본 경험치</summary>
- public int BaseExp { get; set; } = 0;
- /// <summary>기본 포인트</summary>
- public int BasePoint { get; set; } = 0;
- /// <summary>연속 출석 가중치 사용</summary>
- public bool UseStreakBonus { get; set; } = false;
- /// <summary>연속 출석 1일당 추가 경험치</summary>
- public int StreakBonusPerDay { get; set; } = 0;
- /// <summary>연속 출석 1일당 추가 포인트</summary>
- public int StreakBonusPointPerDay { get; set; } = 0;
- /// <summary>가중치 최대 적용 일수</summary>
- public int StreakBonusMaxDays { get; set; } = 0;
- /// <summary>순위 보상 사용</summary>
- public bool UseRankBonus { get; set; } = false;
- /// <summary>순위별 보상 설정 (JSON) [{"rank":1,"exp":100,"point":50},...]</summary>
- public string? RankBonusConfig { get; set; }
- }
- // ==================================================
- // 가입 축하 보상 설정 (SignupReward)
- // 신규 회원 최초 가입 시 1회 지급. 멱등: WalletTransaction RefID "signup:{memberID}"
- // ==================================================
- public sealed class SignupRewardConfig
- {
- /// <summary>가입 축하 보상 활성화</summary>
- public bool Enabled { get; set; } = false;
- /// <summary>지급 코인(무상, Airdrop 파티션)</summary>
- public int CoinAmount { get; set; } = 0;
- /// <summary>지급 캐시(유상 취급, Adjusted 파티션). 기본 0</summary>
- public int CashAmount { get; set; } = 0;
- /// <summary>지급 경험치(XP)</summary>
- public int ExpAmount { get; set; } = 0;
- }
- // ==================================================
- // 보상 엔진 설정 (Reward) — d3 §③ / M2. ActivityTokenConfig 를 대체·통합.
- // RewardService 가 단일 지급 관문에서 참조하는 XP/토큰 수치 + 액션별 일일 캡.
- // 캡 필드는 0 = 무제한. XP=경험치(MemberStats.Exp), Point=토큰(Wallet Reward 파티션).
- // ==================================================
- public sealed class RewardConfig
- {
- /// <summary>게시글 1건 작성 시 지급 경험치 (0 = 미지급)</summary>
- public int PostExp { get; set; } = 0;
- /// <summary>게시글 1건 작성 시 지급 토큰 (0 = 미지급)</summary>
- public int PostPoint { get; set; } = 0;
- /// <summary>댓글 1건 작성 시 지급 경험치 (0 = 미지급)</summary>
- public int CommentExp { get; set; } = 0;
- /// <summary>댓글 1건 작성 시 지급 토큰 (0 = 미지급)</summary>
- public int CommentPoint { get; set; } = 0;
- /// <summary>추천(좋아요)을 누른 회원에게 지급 경험치 (0 = 미지급)</summary>
- public int LikeGivenExp { get; set; } = 0;
- /// <summary>추천(좋아요)을 받은 글 작성자에게 지급 토큰 (0 = 미지급)</summary>
- public int LikeReceivedPoint { get; set; } = 0;
- /// <summary>보상 지급 최소 게시글 길이 (미만이면 미지급, 0 = 제한 없음)</summary>
- public int MinPostLength { get; set; } = 0;
- /// <summary>보상 지급 최소 댓글 길이 (미만이면 미지급, 0 = 제한 없음)</summary>
- public int MinCommentLength { get; set; } = 0;
- /// <summary>신규 가입 후 보상 유예 기간(일) — 가입 N일 이내 회원은 활동 보상 미지급 (어뷰징 방지, 0 = 유예 없음)</summary>
- public int NewMemberHoldDays { get; set; } = 0;
- // ---- 액션별 일일 캡 (0 = 무제한) ----
- /// <summary>게시글 보상 일일 횟수 상한</summary>
- public int PostDailyCount { get; set; } = 0;
- /// <summary>게시글 보상 일일 경험치 상한</summary>
- public int PostDailyExp { get; set; } = 0;
- /// <summary>게시글 보상 일일 토큰 상한</summary>
- public int PostDailyPoint { get; set; } = 0;
- /// <summary>댓글 보상 일일 횟수 상한</summary>
- public int CommentDailyCount { get; set; } = 0;
- /// <summary>댓글 보상 일일 경험치 상한</summary>
- public int CommentDailyExp { get; set; } = 0;
- /// <summary>댓글 보상 일일 토큰 상한</summary>
- public int CommentDailyPoint { get; set; } = 0;
- /// <summary>추천(누른 쪽) 보상 일일 횟수 상한</summary>
- public int LikeGivenDailyCount { get; set; } = 0;
- /// <summary>추천(누른 쪽) 보상 일일 경험치 상한</summary>
- public int LikeGivenDailyExp { get; set; } = 0;
- /// <summary>추천(받은 쪽) 보상 일일 횟수 상한</summary>
- public int LikeReceivedDailyCount { get; set; } = 0;
- /// <summary>추천(받은 쪽) 보상 일일 토큰 상한</summary>
- public int LikeReceivedDailyPoint { get; set; } = 0;
- /// <summary>채팅 보상 일일 횟수 상한</summary>
- public int ChatDailyCount { get; set; } = 0;
- /// <summary>채팅 보상 일일 경험치 상한</summary>
- public int ChatDailyExp { get; set; } = 0;
- // ---- 응원(Cheer) 설정 (D3 M4) ----
- /// <summary>응원 플랫폼 수수료율(%) — fee = floor(amount × CheerFeePercent/100). 기본 20 (Twitch Bits 참고)</summary>
- public int CheerFeePercent { get; set; } = 20;
- /// <summary>1회 응원 최소 금액 (미만이면 거부). 기본 100</summary>
- public int CheerMinAmount { get; set; } = 100;
- /// <summary>한 회원이 하루에 보낼 수 있는 응원 총액 상한 (0 = 무제한). 자전 응원 어뷰징 방지</summary>
- public int CheerDailyMax { get; set; } = 0;
- }
- // ==================================================
- // 모의투자 설정 (Paper) — Admin /Config, d4 §④
- // ==================================================
- public sealed class PaperConfig
- {
- /// <summary>모의투자 노출/주문 토글</summary>
- public bool Enabled { get; set; } = true;
- /// <summary>매매 수수료 Bp (기본 15 = 0.15%; 토큰 sink)</summary>
- public int FeeRateBp { get; set; } = 15;
- /// <summary>매도 거래세 Bp (기본 18; 토큰 sink)</summary>
- public int TaxRateBp { get; set; } = 18;
- /// <summary>최소 입금 토큰</summary>
- public int MinDeposit { get; set; } = 10000;
- /// <summary>계좌 최대 보유 토큰 (0 = 무제한)</summary>
- public int MaxHolding { get; set; } = 0;
- /// <summary>출금 시 수익분 소각 Bp (0 = 꺼둠, 인플레 밸브)</summary>
- public int WithdrawProfitBurnBp { get; set; } = 0;
- /// <summary>1주문 상한 Bp (기본 3000 = Equity 30%)</summary>
- public int OrderMaxPctBp { get; set; } = 3000;
- /// <summary>리더보드 등재 최소 체결 수</summary>
- public int MinFillsForRank { get; set; } = 3;
- }
- // ==================================================
- // 데이터 수집 API 키 + 수집기 활성화 (DataCollection) — Admin /Config/External 하단에서 편집
- // 키는 AES-GCM 암호화 저장(enc:v{n}:), 비면 수집기는 appsettings 폴백. 플래그는 수집기 on/off 의 단일 권위(런타임).
- // ==================================================
- public sealed class DataCollectionConfig
- {
- // ---- 키 (암호화 저장) ----
- /// <summary>공공데이터포털 금융위(data.go.kr) ServiceKey</summary>
- public string? DataGoKrServiceKeyEnc { get; set; }
- /// <summary>KRX(data-dbg.krx.co.kr) AUTH_KEY</summary>
- public string? KrxApiKeyEnc { get; set; }
- /// <summary>OpenDART(공시) crtfc_key</summary>
- public string? OpenDartApiKeyEnc { get; set; }
- /// <summary>수출입은행 현재환율(AP01) authkey</summary>
- public string? KoreaEximExchangeKeyEnc { get; set; }
- /// <summary>수출입은행 대출금리(AP02) authkey</summary>
- public string? KoreaEximLoanRateKeyEnc { get; set; }
- /// <summary>수출입은행 국제금리(AP03) authkey</summary>
- public string? KoreaEximIntlRateKeyEnc { get; set; }
- /// <summary>SEIBro OpenPlatform key</summary>
- public string? SeibroApiKeyEnc { get; set; }
- /// <summary>KOSIS apiKey</summary>
- public string? KosisApiKeyEnc { get; set; }
- // ---- 수집기 활성화 플래그 (appsettings *Sync/Enabled 와 1:1, DB 가 런타임 권위) ----
- public bool StockDataMasterSync { get; set; } = false;
- public bool StockDataDailyPriceSync { get; set; } = false;
- public bool KrxIndexSync { get; set; } = false;
- public bool KrxBondIndexSync { get; set; } = false;
- public bool KrxStockSync { get; set; } = false;
- public bool KrxEtpSync { get; set; } = false;
- public bool KrxWarrantSync { get; set; } = false;
- public bool KrxBondSync { get; set; } = false;
- public bool KrxDerivativeSync { get; set; } = false;
- public bool KrxCommoditySync { get; set; } = false;
- public bool KrxEsgSync { get; set; } = false;
- public bool OpenDartDisclosureSync { get; set; } = false;
- public bool KoreaEximMacroSync { get; set; } = false;
- public bool KosisSync { get; set; } = false;
- public bool WorldIndexEnabled { get; set; } = false;
- public bool MarketQuoteEnabled { get; set; } = false;
- public bool SeibroIssuerSync { get; set; } = false;
- public bool SeibroDividendSync { get; set; } = false;
- public bool SeibroSupplySync { get; set; } = false;
- public bool SeibroCorpActionSync { get; set; } = false;
- public bool SeibroBondSync { get; set; } = false;
- public bool SeibroDerivSync { get; set; } = false;
- public bool SeibroForeignSync { get; set; } = false;
- }
- #endregion
|