1111
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
using System.Net;
|
||||
using LiveRecorder.Application.Abstractions.Auth;
|
||||
using LiveRecorder.Application.Abstractions.Logging;
|
||||
using LiveRecorder.Application.Abstractions.Notifications;
|
||||
using LiveRecorder.Application.Abstractions.Persistence;
|
||||
using LiveRecorder.Application.Abstractions.Platforms;
|
||||
using LiveRecorder.Application.Abstractions.Recording;
|
||||
using LiveRecorder.Application.Abstractions.Settings;
|
||||
using LiveRecorder.Application.Services;
|
||||
using LiveRecorder.Infrastructure.Persistence;
|
||||
using LiveRecorder.Infrastructure.Persistence.Repositories;
|
||||
using LiveRecorder.Infrastructure.Platforms.Bilibili;
|
||||
using LiveRecorder.Infrastructure.Platforms.Douyin;
|
||||
using LiveRecorder.Infrastructure.Platforms.Douyin.Danmaku;
|
||||
using LiveRecorder.Infrastructure.Platforms.Douyin.Signing;
|
||||
using LiveRecorder.Infrastructure.Platforms.Huya;
|
||||
using LiveRecorder.Infrastructure.Services;
|
||||
using LiveRecorder.WebApi.Middleware;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var resetRecordingData = args.Contains("--reset-recording-data", StringComparer.OrdinalIgnoreCase);
|
||||
var corsOrigins = builder.Configuration.GetSection("Cors:Origins").Get<string[]>() ?? ["http://localhost:5173"];
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddMemoryCache();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new OpenApiInfo
|
||||
{
|
||||
Title = "Live Recorder API",
|
||||
Version = "v1",
|
||||
Description = "Multi-platform live recording service"
|
||||
});
|
||||
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||
{
|
||||
In = ParameterLocation.Header,
|
||||
Description = "Input token as: Bearer {token}",
|
||||
Name = "Authorization",
|
||||
Type = SecuritySchemeType.ApiKey
|
||||
});
|
||||
|
||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
Array.Empty<string>()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("frontend", policy =>
|
||||
{
|
||||
policy.WithOrigins(corsOrigins)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddHttpClient("douyin", client =>
|
||||
{
|
||||
client.Timeout = TimeSpan.FromSeconds(20);
|
||||
client.DefaultRequestVersion = HttpVersion.Version11;
|
||||
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
|
||||
})
|
||||
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli,
|
||||
PooledConnectionLifetime = TimeSpan.FromMinutes(2),
|
||||
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30),
|
||||
MaxConnectionsPerServer = 8
|
||||
});
|
||||
|
||||
builder.Services.AddDbContext<LiveRecorderDbContext>(options =>
|
||||
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
builder.Services.AddScoped<IUnitOfWork>(provider => provider.GetRequiredService<LiveRecorderDbContext>());
|
||||
builder.Services.AddScoped<IAppSettingRepository, AppSettingRepository>();
|
||||
builder.Services.AddScoped<ILiveRoomRepository, LiveRoomRepository>();
|
||||
builder.Services.AddScoped<IRecordSessionRepository, RecordSessionRepository>();
|
||||
builder.Services.AddScoped<IRecordTaskRepository, RecordTaskRepository>();
|
||||
builder.Services.AddScoped<IRecordResultRepository, RecordResultRepository>();
|
||||
builder.Services.AddScoped<ISystemLogRepository, SystemLogRepository>();
|
||||
builder.Services.AddScoped<IUserAccountRepository, UserAccountRepository>();
|
||||
builder.Services.AddScoped<IUserSessionRepository, UserSessionRepository>();
|
||||
|
||||
builder.Services.AddScoped<ISystemSettingsService, SystemSettingsService>();
|
||||
builder.Services.AddScoped<ISystemLogService, SystemLogService>();
|
||||
builder.Services.AddScoped<IEmailNotificationService, EmailNotificationService>();
|
||||
builder.Services.AddScoped<IAuthService, AuthService>();
|
||||
builder.Services.AddScoped<LiveRoomService>();
|
||||
builder.Services.AddScoped<LiveRoomStatusService>();
|
||||
builder.Services.AddScoped<RecordService>();
|
||||
builder.Services.AddScoped<RecordSessionService>();
|
||||
builder.Services.AddScoped<StoppedOrphanRecordSessionCleanupService>();
|
||||
builder.Services.AddScoped<DatabaseInitializer>();
|
||||
|
||||
builder.Services.AddScoped<DouyinHttpClient>();
|
||||
builder.Services.AddSingleton<DouyinXBogusSigner>();
|
||||
builder.Services.AddScoped<ILivePlatformAdapter, DouyinLivePlatformAdapter>();
|
||||
builder.Services.AddScoped<ILivePlatformAdapter, BilibiliLivePlatformAdapter>();
|
||||
builder.Services.AddScoped<ILivePlatformAdapter, HuyaLivePlatformAdapter>();
|
||||
builder.Services.AddScoped<ILivePlatformAdapterFactory, LivePlatformAdapterFactory>();
|
||||
builder.Services.AddScoped<ILiveDanmakuAdapter, DouyinDanmakuAdapter>();
|
||||
builder.Services.AddScoped<ILiveDanmakuAdapterFactory, LiveDanmakuAdapterFactory>();
|
||||
|
||||
builder.Services.AddSingleton<IFfmpegService, FfmpegService>();
|
||||
builder.Services.AddScoped<IRecordMediaService, RecordMediaService>();
|
||||
builder.Services.AddHostedService<LiveRoomPollingBackgroundService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.UseCors("frontend");
|
||||
app.UseMiddleware<ApiTokenAuthenticationMiddleware>();
|
||||
|
||||
app.MapGet("/", () => Results.Redirect("/swagger"));
|
||||
app.MapControllers();
|
||||
|
||||
if (!resetRecordingData)
|
||||
{
|
||||
using var scope = app.Services.CreateScope();
|
||||
var initializer = scope.ServiceProvider.GetRequiredService<DatabaseInitializer>();
|
||||
await initializer.InitializeAsync();
|
||||
}
|
||||
|
||||
if (resetRecordingData)
|
||||
{
|
||||
using var scope = app.Services.CreateScope();
|
||||
var dbContext = scope.ServiceProvider.GetRequiredService<LiveRecorderDbContext>();
|
||||
var before = await ReadRecordingDataCountsAsync(dbContext);
|
||||
|
||||
await using (var transaction = await dbContext.Database.BeginTransactionAsync())
|
||||
{
|
||||
await dbContext.Database.ExecuteSqlRawAsync(
|
||||
"DELETE FROM SystemLogEntries WHERE LiveRoomId IS NOT NULL OR RecordSessionId IS NOT NULL OR RecordTaskId IS NOT NULL;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordResults;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordTasks;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordSessions;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM LiveRooms;");
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
|
||||
var after = await ReadRecordingDataCountsAsync(dbContext);
|
||||
Console.WriteLine("Recording data reset complete.");
|
||||
foreach (var key in before.Keys)
|
||||
{
|
||||
Console.WriteLine($"{key}: {before[key]} -> {after[key]}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
app.Run();
|
||||
|
||||
static async Task<Dictionary<string, long>> ReadRecordingDataCountsAsync(LiveRecorderDbContext dbContext)
|
||||
{
|
||||
return new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["LiveRooms"] = await dbContext.LiveRooms.LongCountAsync(),
|
||||
["RecordSessions"] = await dbContext.RecordSessions.LongCountAsync(),
|
||||
["RecordTasks"] = await dbContext.RecordTasks.LongCountAsync(),
|
||||
["RecordResults"] = await dbContext.RecordResults.LongCountAsync(),
|
||||
["SystemLogEntries(Related)"] = await dbContext.SystemLogEntries.LongCountAsync(
|
||||
item => item.LiveRoomId != null || item.RecordSessionId != null || item.RecordTaskId != null)
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user