182 lines
7.4 KiB
C#
182 lines
7.4 KiB
C#
using ChatBot.Data;
|
||
using ChatBot.Data.Interfaces;
|
||
using ChatBot.Data.Repositories;
|
||
using ChatBot.Models.Configuration;
|
||
using ChatBot.Models.Configuration.Validators;
|
||
using ChatBot.Services;
|
||
using ChatBot.Services.HealthChecks;
|
||
using ChatBot.Services.Interfaces;
|
||
using ChatBot.Services.Telegram.Commands;
|
||
using ChatBot.Services.Telegram.Interfaces;
|
||
using ChatBot.Services.Telegram.Services;
|
||
using DotNetEnv;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Options;
|
||
using Serilog;
|
||
using Telegram.Bot;
|
||
|
||
// Загружаем переменные окружения из .env файла
|
||
Env.Load();
|
||
|
||
var builder = Host.CreateApplicationBuilder(args);
|
||
|
||
// Добавляем поддержку переменных окружения в конфигурацию
|
||
builder.Configuration.AddEnvironmentVariables();
|
||
|
||
// Настройка Serilog
|
||
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(builder.Configuration).CreateLogger();
|
||
|
||
try
|
||
{
|
||
Log.ForContext<Program>().Information("Starting Telegram Bot application...");
|
||
|
||
// Добавляем Serilog в DI контейнер
|
||
builder.Services.AddSerilog();
|
||
|
||
// Конфигурируем настройки с валидацией
|
||
builder
|
||
.Services.Configure<TelegramBotSettings>(builder.Configuration.GetSection("TelegramBot"))
|
||
.AddSingleton<IValidateOptions<TelegramBotSettings>, TelegramBotSettingsValidator>();
|
||
|
||
builder
|
||
.Services.Configure<OllamaSettings>(builder.Configuration.GetSection("Ollama"))
|
||
.AddSingleton<IValidateOptions<OllamaSettings>, OllamaSettingsValidator>();
|
||
|
||
builder
|
||
.Services.Configure<AISettings>(builder.Configuration.GetSection("AI"))
|
||
.AddSingleton<IValidateOptions<AISettings>, AISettingsValidator>();
|
||
|
||
builder
|
||
.Services.Configure<DatabaseSettings>(builder.Configuration.GetSection("Database"))
|
||
.AddSingleton<IValidateOptions<DatabaseSettings>, DatabaseSettingsValidator>();
|
||
|
||
// Переопределяем настройки переменными окружения
|
||
builder.Services.Configure<TelegramBotSettings>(settings =>
|
||
{
|
||
settings.BotToken =
|
||
Environment.GetEnvironmentVariable("TELEGRAM_BOT_TOKEN") ?? settings.BotToken;
|
||
});
|
||
|
||
builder.Services.Configure<OllamaSettings>(settings =>
|
||
{
|
||
settings.Url = Environment.GetEnvironmentVariable("OLLAMA_URL") ?? settings.Url;
|
||
settings.DefaultModel =
|
||
Environment.GetEnvironmentVariable("OLLAMA_DEFAULT_MODEL") ?? settings.DefaultModel;
|
||
});
|
||
|
||
builder.Services.Configure<DatabaseSettings>(settings =>
|
||
{
|
||
var host = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost";
|
||
var port = Environment.GetEnvironmentVariable("DB_PORT") ?? "5432";
|
||
var name = Environment.GetEnvironmentVariable("DB_NAME") ?? "chatbot";
|
||
var user = Environment.GetEnvironmentVariable("DB_USER") ?? "postgres";
|
||
var password = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? "postgres";
|
||
|
||
settings.ConnectionString =
|
||
$"Host={host};Port={port};Database={name};Username={user};Password={password}";
|
||
});
|
||
|
||
// Валидируем конфигурацию при старте
|
||
builder.Services.AddOptions<TelegramBotSettings>().ValidateOnStart();
|
||
builder.Services.AddOptions<OllamaSettings>().ValidateOnStart();
|
||
builder.Services.AddOptions<AISettings>().ValidateOnStart();
|
||
builder.Services.AddOptions<DatabaseSettings>().ValidateOnStart();
|
||
|
||
// Регистрируем IOllamaClient
|
||
builder.Services.AddSingleton<IOllamaClient>(sp =>
|
||
{
|
||
var settings = sp.GetRequiredService<IOptions<OllamaSettings>>();
|
||
return new OllamaClientAdapter(settings.Value.Url);
|
||
});
|
||
|
||
// Регистрируем Entity Framework и базу данных
|
||
builder.Services.AddDbContext<ChatBotDbContext>(
|
||
(serviceProvider, options) =>
|
||
{
|
||
var dbSettings = serviceProvider.GetRequiredService<IOptions<DatabaseSettings>>().Value;
|
||
options.UseNpgsql(
|
||
dbSettings.ConnectionString,
|
||
npgsqlOptions =>
|
||
{
|
||
npgsqlOptions.CommandTimeout(dbSettings.CommandTimeout);
|
||
}
|
||
);
|
||
|
||
if (dbSettings.EnableSensitiveDataLogging)
|
||
{
|
||
options.EnableSensitiveDataLogging();
|
||
}
|
||
}
|
||
);
|
||
|
||
// Регистрируем репозиторий
|
||
builder.Services.AddScoped<IChatSessionRepository, ChatSessionRepository>();
|
||
|
||
// Регистрируем интерфейсы и сервисы
|
||
// Можно переключиться между InMemorySessionStorage и DatabaseSessionStorage
|
||
builder.Services.AddScoped<ISessionStorage, DatabaseSessionStorage>();
|
||
|
||
// Регистрируем основные сервисы
|
||
builder.Services.AddSingleton<ModelService>();
|
||
builder.Services.AddSingleton<SystemPromptService>();
|
||
builder.Services.AddSingleton<IHistoryCompressionService, HistoryCompressionService>();
|
||
builder.Services.AddSingleton<IAIService, AIService>();
|
||
builder.Services.AddScoped<ChatService>();
|
||
|
||
// Регистрируем сервис инициализации базы данных
|
||
builder.Services.AddHostedService<DatabaseInitializationService>();
|
||
|
||
// Регистрируем Telegram команды
|
||
builder.Services.AddScoped<ITelegramCommand, StartCommand>();
|
||
builder.Services.AddScoped<ITelegramCommand, HelpCommand>();
|
||
builder.Services.AddScoped<ITelegramCommand, ClearCommand>();
|
||
builder.Services.AddScoped<ITelegramCommand, SettingsCommand>();
|
||
builder.Services.AddScoped<ITelegramCommand, StatusCommand>();
|
||
|
||
// Регистрируем Telegram сервисы
|
||
builder.Services.AddSingleton<ITelegramBotClient>(provider =>
|
||
{
|
||
var settings = provider.GetRequiredService<IOptions<TelegramBotSettings>>();
|
||
return new TelegramBotClient(settings.Value.BotToken);
|
||
});
|
||
builder.Services.AddSingleton<ITelegramMessageSender, TelegramMessageSender>();
|
||
builder.Services.AddSingleton<ITelegramErrorHandler, TelegramErrorHandler>();
|
||
builder.Services.AddScoped<CommandRegistry>();
|
||
builder.Services.AddSingleton<BotInfoService>();
|
||
builder.Services.AddScoped<ITelegramCommandProcessor, TelegramCommandProcessor>();
|
||
builder.Services.AddScoped<ITelegramMessageHandler, TelegramMessageHandler>();
|
||
|
||
// Регистрируем TelegramBotService как singleton и hosted service
|
||
builder.Services.AddSingleton<ITelegramBotService, TelegramBotService>();
|
||
builder.Services.AddSingleton<IHostedService>(provider =>
|
||
(IHostedService)provider.GetRequiredService<ITelegramBotService>()
|
||
);
|
||
|
||
// Регистрируем Health Checks
|
||
var ollamaTags = new[] { "api", "ollama" };
|
||
var telegramTags = new[] { "api", "telegram" };
|
||
|
||
builder
|
||
.Services.AddHealthChecks()
|
||
.AddCheck<OllamaHealthCheck>("ollama", tags: ollamaTags)
|
||
.AddCheck<TelegramBotHealthCheck>("telegram", tags: telegramTags);
|
||
|
||
var host = builder.Build();
|
||
|
||
// Инициализируем ModelService
|
||
var modelService = host.Services.GetRequiredService<ModelService>();
|
||
await modelService.InitializeAsync();
|
||
|
||
Log.ForContext<Program>().Information("All services initialized successfully");
|
||
|
||
await host.RunAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.ForContext<Program>().Fatal(ex, "Application terminated unexpectedly");
|
||
}
|
||
finally
|
||
{
|
||
await Log.CloseAndFlushAsync();
|
||
}
|