littleshop/TeleBot/TeleBot/Program.cs
SysAdmin a1af91807e
All checks were successful
Build and Deploy LittleShop / Deploy to Production VPS (Manual Only) (push) Has been skipped
Build and Deploy LittleShop / Deploy to Pre-Production (CT109) (push) Successful in 1m1s
feat: Add TeleBot session tracking to LittleShop and fix live activity feed ordering
- Add LittleShopSessionId and MessageCount properties to UserSession model
- Integrate SessionManager with BotManagerService for remote session tracking
- Wire up SessionManager.SetBotManagerService() at startup in Program.cs
- Create remote sessions via BotManagerService.StartSessionAsync() when users connect
- Update remote sessions periodically (every 10 messages) via UpdateSessionAsync()
- Fix live activity feed to show newest records at top by reversing array iteration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 20:03:08 +00:00

185 lines
7.1 KiB
C#

using System;
using System.IO;
using System.Threading.Tasks;
using Hangfire;
using Hangfire.LiteDB;
using LittleShop.Client.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using TeleBot;
using TeleBot.Handlers;
using TeleBot.Services;
using TeleBot.Http;
using TeleBot.UI;
var builder = WebApplication.CreateBuilder(args);
var BrandName = "Little Shop";
// Configuration
builder.Configuration
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
// Add MVC Controllers for webhook endpoints
builder.Services.AddControllers();
// Serilog
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("logs/telebot-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog();
// Services
builder.Services.AddSingleton<IPrivacyService, PrivacyService>();
builder.Services.AddSingleton<SessionManager>();
builder.Services.AddSingleton<ISessionManager>(provider => provider.GetRequiredService<SessionManager>());
builder.Services.AddHostedService<SessionManager>(provider => provider.GetRequiredService<SessionManager>());
// LittleShop Client with TOR support
builder.Services.AddLittleShopClient(options =>
{
var config = builder.Configuration;
options.BaseUrl = config["LittleShop:ApiUrl"] ?? "https://localhost:5001";
options.TimeoutSeconds = 30;
options.MaxRetryAttempts = 3;
// Set the brand name globally
BotConfig.BrandName = config["LittleShop:BrandName"] ?? "Little Shop";
},
// Pass TOR configuration
useTorProxy: builder.Configuration.GetValue<bool>("LittleShop:UseTor"),
torSocksHost: builder.Configuration.GetValue<string>("Privacy:TorSocksHost") ?? "127.0.0.1",
torSocksPort: builder.Configuration.GetValue<int>("Privacy:TorSocksPort", 9050));
builder.Services.AddSingleton<ILittleShopService, LittleShopService>();
// Redis (if enabled)
if (builder.Configuration.GetValue<bool>("Redis:Enabled"))
{
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration["Redis:ConnectionString"] ?? "localhost:6379";
options.InstanceName = builder.Configuration["Redis:InstanceName"] ?? "TeleBot";
});
}
// Hangfire (if enabled)
if (builder.Configuration.GetValue<bool>("Hangfire:Enabled"))
{
var hangfireDb = builder.Configuration["Hangfire:DatabasePath"] ?? "hangfire.db";
builder.Services.AddHangfire(config =>
{
config.UseLiteDbStorage(hangfireDb);
});
builder.Services.AddHangfireServer();
}
// Bot Handlers
builder.Services.AddSingleton<ICommandHandler, CommandHandler>();
builder.Services.AddSingleton<ICallbackHandler, CallbackHandler>();
builder.Services.AddSingleton<IMessageHandler, MessageHandler>();
// Callback Data Mapper (for short IDs to avoid Telegram's 64-byte limit)
builder.Services.AddSingleton<CallbackDataMapper>();
builder.Services.AddSingleton<MenuBuilder>();
// Bot Manager Service (for registration and metrics) - Single instance with direct connection (internal API)
builder.Services.AddHttpClient<BotManagerService>()
.ConfigurePrimaryHttpMessageHandler(sp =>
{
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("BotManager");
return Socks5HttpHandler.CreateDirect(logger);
});
builder.Services.AddSingleton<BotManagerService>();
builder.Services.AddHostedService(provider => provider.GetRequiredService<BotManagerService>());
// Liveness Service - Monitors LittleShop connectivity and triggers shutdown on failure
builder.Services.AddHttpClient<LivenessService>()
.ConfigurePrimaryHttpMessageHandler(sp =>
{
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("Liveness");
return Socks5HttpHandler.CreateDirect(logger);
});
builder.Services.AddSingleton<LivenessService>();
builder.Services.AddHostedService(provider => provider.GetRequiredService<LivenessService>());
// Message Delivery Service - Single instance
builder.Services.AddSingleton<MessageDeliveryService>();
builder.Services.AddSingleton<IMessageDeliveryService>(sp => sp.GetRequiredService<MessageDeliveryService>());
builder.Services.AddHostedService<MessageDeliveryService>(sp => sp.GetRequiredService<MessageDeliveryService>());
// Bot Activity Tracking with direct connection (internal API)
builder.Services.AddHttpClient<IBotActivityTracker, BotActivityTracker>()
.ConfigurePrimaryHttpMessageHandler(sp =>
{
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("ActivityTracker");
return Socks5HttpHandler.CreateDirect(logger);
});
// Product Carousel Service with direct connection (internal API)
builder.Services.AddHttpClient<ProductCarouselService>()
.ConfigurePrimaryHttpMessageHandler(sp =>
{
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("Carousel");
return Socks5HttpHandler.CreateDirect(logger);
});
builder.Services.AddSingleton<IProductCarouselService, ProductCarouselService>();
// Bot Service - Single instance
builder.Services.AddSingleton<TelegramBotService>();
builder.Services.AddHostedService(provider => provider.GetRequiredService<TelegramBotService>());
// Build the application
var app = builder.Build();
// Connect the services
var botManagerService = app.Services.GetRequiredService<BotManagerService>();
var telegramBotService = app.Services.GetRequiredService<TelegramBotService>();
botManagerService.SetTelegramBotService(telegramBotService);
// Connect SessionManager to BotManagerService for remote session tracking
var sessionManager = app.Services.GetRequiredService<SessionManager>();
sessionManager.SetBotManagerService(botManagerService);
// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.MapControllers();
try
{
Log.Information("Starting TeleBot - Privacy-First E-Commerce Bot");
Log.Information("Privacy Mode: {PrivacyMode}", builder.Configuration["Privacy:Mode"]);
Log.Information("Ephemeral by Default: {Ephemeral}", builder.Configuration["Privacy:EphemeralByDefault"]);
Log.Information("Tor Enabled: {Tor}", builder.Configuration["Privacy:EnableTor"]);
Log.Information("Discovery endpoint: GET /api/discovery/probe");
Log.Information("LittleShop API: {ApiUrl}", builder.Configuration["LittleShop:ApiUrl"]);
Log.Information("Webhook endpoints available at /api/webhook");
await app.RunAsync();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}