161 lines
4.7 KiB
C#
161 lines
4.7 KiB
C#
using FluentValidation;
|
|
using GreenHome.AI.DeepSeek;
|
|
using GreenHome.Application;
|
|
using GreenHome.Infrastructure;
|
|
using GreenHome.Infrastructure.Data;
|
|
using GreenHome.Sms.Ippanel;
|
|
using GreenHome.VoiceCall.Avanak;
|
|
using Microsoft.AspNetCore.StaticFiles;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.FileProviders;
|
|
using Scalar.AspNetCore;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// ============================================================
|
|
// 1. Service Registration
|
|
// ============================================================
|
|
|
|
ConfigureCoreServices(builder);
|
|
ConfigureCors(builder);
|
|
ConfigureExternalServices(builder);
|
|
|
|
var app = builder.Build();
|
|
|
|
// ============================================================
|
|
// 2. Pipeline Configuration
|
|
// ============================================================
|
|
|
|
ApplyMigrations(app);
|
|
ConfigureMiddleware(app);
|
|
ConfigureStaticFiles(app);
|
|
app.MapControllers();
|
|
|
|
// SPA fallback: serve index.html for non-API routes (client-side routing)
|
|
app.MapFallbackToFile("index.html");
|
|
|
|
app.Run();
|
|
|
|
// ============================================================
|
|
// Service Registration Methods
|
|
// ============================================================
|
|
|
|
void ConfigureCoreServices(WebApplicationBuilder builder)
|
|
{
|
|
builder.Services.AddControllers();
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddOpenApi();
|
|
|
|
// Caching & HTTP client factory (used by WeatherController proxy with tiered caching)
|
|
builder.Services.AddMemoryCache();
|
|
builder.Services.AddHttpClient();
|
|
|
|
builder.Services.AddAutoMapper(typeof(GreenHome.Application.MappingProfile));
|
|
builder.Services.AddValidatorsFromAssemblyContaining<GreenHome.Application.DeviceDtoValidator>();
|
|
|
|
builder.Services.AddInfrastructure(builder.Configuration);
|
|
}
|
|
|
|
void ConfigureCors(WebApplicationBuilder builder)
|
|
{
|
|
const string CorsPolicy = "DefaultCors";
|
|
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy(CorsPolicy, policy =>
|
|
{
|
|
if (builder.Environment.IsDevelopment())
|
|
{
|
|
policy
|
|
.AllowAnyOrigin()
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod();
|
|
}
|
|
else
|
|
{
|
|
policy
|
|
.WithOrigins(
|
|
"http://green.nabaksoft.ir",
|
|
"https://green.nabaksoft.ir",
|
|
"http://gh1.nabaksoft.ir",
|
|
"https://gh1.nabaksoft.ir"
|
|
)
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod()
|
|
.AllowCredentials();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
void ConfigureExternalServices(WebApplicationBuilder builder)
|
|
{
|
|
builder.Services.AddIppanelSms(builder.Configuration);
|
|
builder.Services.AddAvanakVoiceCall(builder.Configuration);
|
|
builder.Services.AddDeepSeek(builder.Configuration);
|
|
}
|
|
|
|
// ============================================================
|
|
// Middleware & Pipeline Methods
|
|
// ============================================================
|
|
|
|
void ApplyMigrations(WebApplication app)
|
|
{
|
|
using var scope = app.Services.CreateScope();
|
|
var services = scope.ServiceProvider;
|
|
|
|
try
|
|
{
|
|
var context = services.GetRequiredService<GreenHomeDbContext>();
|
|
context.Database.Migrate();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var logger = services.GetRequiredService<ILogger<Program>>();
|
|
logger.LogError(ex, "An error occurred while migrating the database.");
|
|
}
|
|
}
|
|
|
|
void ConfigureMiddleware(WebApplication app)
|
|
{
|
|
app.MapOpenApi();
|
|
app.MapScalarApiReference();
|
|
|
|
if (!app.Environment.IsDevelopment())
|
|
{
|
|
app.UseHttpsRedirection();
|
|
}
|
|
|
|
app.UseCors("DefaultCors");
|
|
app.UseAuthorization();
|
|
}
|
|
|
|
void ConfigureStaticFiles(WebApplication app)
|
|
{
|
|
var provider = new FileExtensionContentTypeProvider();
|
|
provider.Mappings[".amr"] = "audio/amr";
|
|
provider.Mappings[".apk"] = "application/vnd.android.package-archive";
|
|
|
|
// Serve existing My_StaticFiles folder
|
|
app.UseStaticFiles(new StaticFileOptions
|
|
{
|
|
FileProvider = new PhysicalFileProvider(
|
|
Path.Combine(app.Environment.ContentRootPath, "My_StaticFiles")),
|
|
RequestPath = "/My_StaticFiles",
|
|
ContentTypeProvider = provider
|
|
});
|
|
|
|
// Serve new files folder for APK and other downloads
|
|
app.UseStaticFiles(new StaticFileOptions
|
|
{
|
|
FileProvider = new PhysicalFileProvider(
|
|
Path.Combine(app.Environment.ContentRootPath, "files")),
|
|
RequestPath = "/files",
|
|
ContentTypeProvider = provider
|
|
});
|
|
|
|
// Serve the SPA from wwwroot (Vite build output)
|
|
app.UseDefaultFiles();
|
|
app.UseStaticFiles();
|
|
}
|