Add customer communication system
This commit is contained in:
308
TeleBot/TeleBotClient/BotSimulator.cs
Normal file
308
TeleBot/TeleBotClient/BotSimulator.cs
Normal file
@@ -0,0 +1,308 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bogus;
|
||||
using LittleShop.Client;
|
||||
using LittleShop.Client.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace TeleBotClient
|
||||
{
|
||||
public class BotSimulator
|
||||
{
|
||||
private readonly ILittleShopClient _client;
|
||||
private readonly ILogger<BotSimulator> _logger;
|
||||
private readonly Random _random;
|
||||
private readonly Faker _faker;
|
||||
private List<Category> _categories = new();
|
||||
private List<Product> _products = new();
|
||||
|
||||
public BotSimulator(ILittleShopClient client, ILogger<BotSimulator> logger)
|
||||
{
|
||||
_client = client;
|
||||
_logger = logger;
|
||||
_random = new Random();
|
||||
_faker = new Faker();
|
||||
}
|
||||
|
||||
public async Task<SimulationResult> SimulateUserSession()
|
||||
{
|
||||
var result = new SimulationResult
|
||||
{
|
||||
SessionId = Guid.NewGuid().ToString(),
|
||||
StartTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("🤖 Starting bot simulation session {SessionId}", result.SessionId);
|
||||
|
||||
// Step 1: Authenticate
|
||||
_logger.LogInformation("📝 Authenticating with API...");
|
||||
if (!await Authenticate())
|
||||
{
|
||||
result.Success = false;
|
||||
result.ErrorMessage = "Authentication failed";
|
||||
return result;
|
||||
}
|
||||
result.Steps.Add("✅ Authentication successful");
|
||||
|
||||
// Step 2: Browse categories
|
||||
_logger.LogInformation("📁 Browsing categories...");
|
||||
await BrowseCategories();
|
||||
result.Steps.Add($"✅ Found {_categories.Count} categories");
|
||||
|
||||
// Step 3: Select random category and browse products
|
||||
if (_categories.Any())
|
||||
{
|
||||
var selectedCategory = _categories[_random.Next(_categories.Count)];
|
||||
_logger.LogInformation("🔍 Selected category: {Category}", selectedCategory.Name);
|
||||
result.Steps.Add($"✅ Selected category: {selectedCategory.Name}");
|
||||
|
||||
await BrowseProducts(selectedCategory.Id);
|
||||
result.Steps.Add($"✅ Found {_products.Count} products in category");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Browse all products if no categories
|
||||
await BrowseProducts(null);
|
||||
result.Steps.Add($"✅ Found {_products.Count} total products");
|
||||
}
|
||||
|
||||
// Step 4: Build shopping cart
|
||||
_logger.LogInformation("🛒 Building shopping cart...");
|
||||
var cart = BuildRandomCart();
|
||||
result.Cart = cart;
|
||||
result.Steps.Add($"✅ Added {cart.Items.Count} items to cart (Total: ${cart.TotalAmount:F2})");
|
||||
|
||||
// Step 5: Generate shipping information
|
||||
_logger.LogInformation("📦 Generating shipping information...");
|
||||
var shippingInfo = GenerateShippingInfo();
|
||||
result.ShippingInfo = shippingInfo;
|
||||
result.Steps.Add($"✅ Generated shipping to {shippingInfo.City}, {shippingInfo.Country}");
|
||||
|
||||
// Step 6: Create order
|
||||
_logger.LogInformation("📝 Creating order...");
|
||||
var order = await CreateOrder(cart, shippingInfo);
|
||||
if (order != null)
|
||||
{
|
||||
result.OrderId = order.Id;
|
||||
result.OrderTotal = order.TotalAmount;
|
||||
result.Steps.Add($"✅ Order created: {order.Id}");
|
||||
|
||||
// Step 7: Select payment method
|
||||
var currency = SelectRandomCurrency();
|
||||
_logger.LogInformation("💰 Selected payment method: {Currency}", currency);
|
||||
result.PaymentCurrency = currency;
|
||||
result.Steps.Add($"✅ Selected payment: {currency}");
|
||||
|
||||
// Step 8: Create payment
|
||||
var payment = await CreatePayment(order.Id, currency);
|
||||
if (payment != null)
|
||||
{
|
||||
result.PaymentId = payment.Id;
|
||||
result.PaymentAddress = payment.WalletAddress;
|
||||
result.PaymentAmount = payment.RequiredAmount;
|
||||
result.Steps.Add($"✅ Payment created: {payment.RequiredAmount} {currency}");
|
||||
}
|
||||
}
|
||||
|
||||
result.Success = true;
|
||||
result.EndTime = DateTime.UtcNow;
|
||||
result.Duration = result.EndTime - result.StartTime;
|
||||
|
||||
_logger.LogInformation("✅ Simulation completed successfully in {Duration}", result.Duration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "❌ Simulation failed");
|
||||
result.Success = false;
|
||||
result.ErrorMessage = ex.Message;
|
||||
result.EndTime = DateTime.UtcNow;
|
||||
result.Duration = result.EndTime - result.StartTime;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> Authenticate()
|
||||
{
|
||||
var result = await _client.Authentication.LoginAsync("admin", "admin");
|
||||
if (result.IsSuccess && result.Data != null && !string.IsNullOrEmpty(result.Data.Token))
|
||||
{
|
||||
_client.Authentication.SetToken(result.Data.Token);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task BrowseCategories()
|
||||
{
|
||||
var result = await _client.Catalog.GetCategoriesAsync();
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
_categories = result.Data;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BrowseProducts(Guid? categoryId)
|
||||
{
|
||||
var result = await _client.Catalog.GetProductsAsync(
|
||||
pageNumber: 1,
|
||||
pageSize: 50,
|
||||
categoryId: categoryId
|
||||
);
|
||||
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
_products = result.Data.Items;
|
||||
}
|
||||
}
|
||||
|
||||
private ShoppingCart BuildRandomCart()
|
||||
{
|
||||
var cart = new ShoppingCart();
|
||||
|
||||
if (!_products.Any())
|
||||
return cart;
|
||||
|
||||
// Random number of items (1-5)
|
||||
var itemCount = _random.Next(1, Math.Min(6, _products.Count + 1));
|
||||
var selectedProducts = _products.OrderBy(x => _random.Next()).Take(itemCount).ToList();
|
||||
|
||||
foreach (var product in selectedProducts)
|
||||
{
|
||||
var quantity = _random.Next(1, 4); // 1-3 items
|
||||
cart.AddItem(product.Id, product.Name, product.Price, quantity);
|
||||
_logger.LogDebug("Added {Quantity}x {Product} @ ${Price}",
|
||||
quantity, product.Name, product.Price);
|
||||
}
|
||||
|
||||
return cart;
|
||||
}
|
||||
|
||||
private ShippingInfo GenerateShippingInfo()
|
||||
{
|
||||
return new ShippingInfo
|
||||
{
|
||||
IdentityReference = $"SIM-{Guid.NewGuid().ToString().Substring(0, 8).ToUpper()}",
|
||||
Name = _faker.Name.FullName(),
|
||||
Address = _faker.Address.StreetAddress(),
|
||||
City = _faker.Address.City(),
|
||||
PostCode = _faker.Address.ZipCode(),
|
||||
Country = _faker.PickRandom(new[] { "United Kingdom", "Ireland", "France", "Germany", "Netherlands" }),
|
||||
Notes = _faker.Lorem.Sentence()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<Order?> CreateOrder(ShoppingCart cart, ShippingInfo shipping)
|
||||
{
|
||||
var request = new CreateOrderRequest
|
||||
{
|
||||
IdentityReference = shipping.IdentityReference,
|
||||
ShippingName = shipping.Name,
|
||||
ShippingAddress = shipping.Address,
|
||||
ShippingCity = shipping.City,
|
||||
ShippingPostCode = shipping.PostCode,
|
||||
ShippingCountry = shipping.Country,
|
||||
Notes = shipping.Notes,
|
||||
Items = cart.Items.Select(i => new CreateOrderItem
|
||||
{
|
||||
ProductId = i.ProductId,
|
||||
Quantity = i.Quantity
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
var result = await _client.Orders.CreateOrderAsync(request);
|
||||
return result.IsSuccess ? result.Data : null;
|
||||
}
|
||||
|
||||
private string SelectRandomCurrency()
|
||||
{
|
||||
var currencies = new[] { "BTC", "XMR", "USDT", "LTC", "ETH", "ZEC", "DASH", "DOGE" };
|
||||
|
||||
// Weight towards BTC and XMR
|
||||
var weights = new[] { 30, 25, 15, 10, 10, 5, 3, 2 };
|
||||
var totalWeight = weights.Sum();
|
||||
var randomValue = _random.Next(totalWeight);
|
||||
|
||||
var currentWeight = 0;
|
||||
for (int i = 0; i < currencies.Length; i++)
|
||||
{
|
||||
currentWeight += weights[i];
|
||||
if (randomValue < currentWeight)
|
||||
return currencies[i];
|
||||
}
|
||||
|
||||
return "BTC";
|
||||
}
|
||||
|
||||
private async Task<CryptoPayment?> CreatePayment(Guid orderId, string currency)
|
||||
{
|
||||
var result = await _client.Orders.CreatePaymentAsync(orderId, currency);
|
||||
return result.IsSuccess ? result.Data : null;
|
||||
}
|
||||
}
|
||||
|
||||
public class SimulationResult
|
||||
{
|
||||
public string SessionId { get; set; } = string.Empty;
|
||||
public bool Success { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public List<string> Steps { get; set; } = new();
|
||||
|
||||
// Order details
|
||||
public Guid? OrderId { get; set; }
|
||||
public decimal OrderTotal { get; set; }
|
||||
public ShoppingCart? Cart { get; set; }
|
||||
public ShippingInfo? ShippingInfo { get; set; }
|
||||
|
||||
// Payment details
|
||||
public Guid? PaymentId { get; set; }
|
||||
public string? PaymentCurrency { get; set; }
|
||||
public string? PaymentAddress { get; set; }
|
||||
public decimal PaymentAmount { get; set; }
|
||||
}
|
||||
|
||||
public class ShoppingCart
|
||||
{
|
||||
public List<CartItem> Items { get; set; } = new();
|
||||
public decimal TotalAmount => Items.Sum(i => i.TotalPrice);
|
||||
|
||||
public void AddItem(Guid productId, string name, decimal price, int quantity)
|
||||
{
|
||||
Items.Add(new CartItem
|
||||
{
|
||||
ProductId = productId,
|
||||
ProductName = name,
|
||||
UnitPrice = price,
|
||||
Quantity = quantity,
|
||||
TotalPrice = price * quantity
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class CartItem
|
||||
{
|
||||
public Guid ProductId { get; set; }
|
||||
public string ProductName { get; set; } = string.Empty;
|
||||
public decimal UnitPrice { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
public decimal TotalPrice { get; set; }
|
||||
}
|
||||
|
||||
public class ShippingInfo
|
||||
{
|
||||
public string IdentityReference { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string City { get; set; } = string.Empty;
|
||||
public string PostCode { get; set; } = string.Empty;
|
||||
public string Country { get; set; } = string.Empty;
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user