Families.Web 1.0.0.0
사진, 동영상, 글, 댓글과 반응을 가족끼리만 공유하는 비공개 앨범·타임라인 서비스입니다.
로딩중...
검색중...
일치하는것 없음
Program.cs
이 파일의 문서화 페이지로 가기
1using System.IO;
2using Dreamine.Hybrid.Wpf.DependencyInjection;
3using Dreamine.Hybrid.Wpf.Hosting;
4using Dreamine.Identity;
5using Dreamine.Identity.Options;
6using Microsoft.AspNetCore.Components.Server;
7using Microsoft.Extensions.Configuration;
8using Microsoft.Extensions.DependencyInjection;
9using Microsoft.Extensions.Hosting;
10using FamiliesApp.Blazor;
12
13namespace FamiliesApp;
14
23public static class Program
24{
33 [STAThread]
34 public static void Main()
35 {
36 HostApplicationBuilder builder = Host.CreateApplicationBuilder();
37 builder.Configuration.AddUserSecrets("codemaru-oauth-2ba4e1b2");
38
39 int serverPort = GetInt(builder.Configuration, "FamilyServer:Port", 5080);
40 bool listenAnyIp = GetBool(builder.Configuration, "FamilyServer:ListenAnyIp", true);
41 AuthOptions authOptions =
42 builder.Configuration.GetSection(AuthOptions.SectionName).Get<AuthOptions>() ?? new AuthOptions();
43 string usersDbPath = ResolvePath(
44 builder.Configuration[$"{AuthOptions.SectionName}:UsersDbPath"],
45 Path.Combine(AppContext.BaseDirectory, "App_Data", "codemaru.db"));
46
47 builder.Services.AddDreamineHybridWpf();
48 builder.Services.AddDreamineIdentityWpfHost();
49
50 var familyOpts = FamilyOptions.From(builder.Configuration);
51 builder.Services.AddSingleton(familyOpts);
52 builder.Services.AddSingleton<IFamilyTenantStore, JsonFamilyTenantStore>();
53 builder.Services.AddSingleton<IPostStore, JsonPostStore>();
54 builder.Services.AddSingleton<IAlbumStore, JsonAlbumStore>();
55 builder.Services.AddSingleton<IGlobalSettingsStore, JsonGlobalSettingsStore>();
56 builder.Services.AddSingleton<IMediaService, LocalMediaService>();
57 builder.Services.AddSingleton<IReactionStore, JsonReactionStore>();
58
59 builder.Services.AddSingleton<Views.MainWindow>();
60 builder.Services.AddHostedService<GhostAccountCleanupService>();
61
62 builder.Services.AddDreamineBlazorServer<AppShell>(options =>
63 {
64 options.Port = serverPort;
65 options.ListenAnyIp = listenAnyIp;
66 options.SharedServiceTypes.Add(typeof(FamilyOptions));
67 options.SharedServiceTypes.Add(typeof(IFamilyTenantStore));
68 options.SharedServiceTypes.Add(typeof(IPostStore));
69 options.SharedServiceTypes.Add(typeof(IAlbumStore));
70 options.SharedServiceTypes.Add(typeof(IGlobalSettingsStore));
71 options.SharedServiceTypes.Add(typeof(IMediaService));
72 options.SharedServiceTypes.Add(typeof(IReactionStore));
73 options.AddPhysicalStaticFiles(familyOpts.ResolvedDataPath, "/family-data");
74
75 // InputFile(사진·동영상 업로드)은 SignalR 회선을 통해 청크 단위로 전송되는데,
76 // 기본 SignalR 메시지 크기 제한(32KB)과 짧은 타임아웃 때문에 큰 파일은 매우 느리거나
77 // 응답 없이 멈춘 것처럼 보입니다. 업로드 용량 검증은 LocalMediaService에서 별도로
78 // 하고 있으므로 전송 한도 자체는 풀어줍니다.
79 options.ConfigureServices = services =>
80 {
81 services.AddServerSideBlazor().AddHubOptions(o =>
82 {
83 o.MaximumReceiveMessageSize = null;
84 o.ClientTimeoutInterval = TimeSpan.FromMinutes(10);
85 o.HandshakeTimeout = TimeSpan.FromMinutes(2);
86 o.KeepAliveInterval = TimeSpan.FromSeconds(10);
87 });
88
89 services.AddAntiforgery(o =>
90 {
91 o.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
92 o.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest;
93 });
94
95 services.Configure<CircuitOptions>(o =>
96 {
97 o.DisconnectedCircuitMaxRetained = 100;
98 o.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3);
99 o.JSInteropDefaultCallTimeout = TimeSpan.FromMinutes(1);
100 o.MaxBufferedUnacknowledgedRenderBatches = 10;
101 });
102
103 services.AddScoped<FamilyUserContext>();
104 };
105
106 options.AddDreamineIdentity(authOptions, usersDbPath);
107 });
108
109 // OG 플랫폼 이미지 자동 생성 (없을 때만)
110 var wwwroot = Path.Combine(AppContext.BaseDirectory, "wwwroot");
111 try { OgImageGenerator.EnsureGenerated(wwwroot); } catch { /* 실패해도 앱 계속 실행 */ }
112
113 builder.Build().RunDreamineWpfApp<App>();
114 }
115
156 private static int GetInt(IConfiguration cfg, string key, int fallback) =>
157 int.TryParse(cfg[key], out int v) ? v : fallback;
158
199 private static bool GetBool(IConfiguration cfg, string key, bool fallback) =>
200 bool.TryParse(cfg[key], out bool v) ? v : fallback;
201
234 private static string ResolvePath(string? configuredPath, string fallback)
235 {
236 if (string.IsNullOrWhiteSpace(configuredPath))
237 {
238 return fallback;
239 }
240
241 return Path.IsPathRooted(configuredPath)
242 ? configuredPath
243 : Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, configuredPath));
244 }
245}
static string ResolvePath(string? configuredPath, string fallback)
Definition Program.cs:234
static void Main()
Definition Program.cs:34
static bool GetBool(IConfiguration cfg, string key, bool fallback)
Definition Program.cs:199
static int GetInt(IConfiguration cfg, string key, int fallback)
Definition Program.cs:156
static FamilyOptions From(IConfiguration configuration)
static void EnsureGenerated(string wwwrootPath)