Problem:
- Selecting Size then Color would reset Size selection
- Users could never get "Add to Cart" button with multiple variant types
- Each selection created a NEW list, wiping previous choices
Root Cause:
- HandleSetVariant created: new List<string> { variantName }
- This replaced all previous selections instead of accumulating
Fix:
1. Get existing selected variants from session
2. Find the variant type of newly selected variant
3. Remove any previous selection from the SAME type (allow changing choice)
4. Add the new selection
5. Save accumulated list back to session
Example behavior now:
- Select "Red" (Color) → selectedVariants = ["Red"]
- Select "Large" (Size) → selectedVariants = ["Red", "Large"] ✅
- Select "Blue" (Color) → selectedVariants = ["Blue", "Large"] ✅
- Can now confirm when all types selected
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
- Product with Size + Color only required selecting 1 variant total
- User could add to cart after selecting just Size OR Color, not both
Root Cause:
- Logic checked if selectedVariants.Count == 1 for single items
- Didn't verify that all variant types were covered
Fix:
- For single items: Check that each variant type has at least one selection
- Logic: variantGroups.All(g => g.Any(v => selectedVariants.Contains(v.Name)))
- For multi-buy: Keep existing logic (total count == quantity)
Now users must select:
- Size + Color products: Must pick both Size AND Color
- Size only products: Must pick Size only
- Etc.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- OrderListMenu now shows item summary (e.g., '2x Product Name' or 'Product Name +2 more')
- FormatCart enhanced to show variant selections and multi-buy indicators
- FormatOrder enhanced to show variant names and detailed item breakdown
- Cart now clearly distinguishes between multi-buy bundles and regular items
- Order confirmations now show full product and variant details
Replaced generic GUID displays with human-readable product information for better UX.
- Changed HandleMainMenu to send new messages instead of editing
- Changed HandleBrowse to send new messages for category navigation
- Changed HandleViewCart to use SendNewCartMessage (already existed)
- Changed HandleViewOrders to send new messages for order list
- Changed HandleViewOrder to send new messages for order details
This ensures the active conversation always appears at the bottom of the chat
instead of mid-thread when users click menu buttons. Provides better UX and
natural conversation flow in Telegram.
- Added SavedShippingAddress model to store user addresses
- Added Privacy.SaveShippingAddress preference (null = not asked, true/false = user choice)
- Enhanced checkout flow to offer using saved address if available
- Ask once about saving address, respect user's choice going forward
- Automatically save/not save based on user preference in future orders
- Added menu options: Use Saved Address, Enter New Address, Save Address (Yes/No)
- Enhanced CallbackHandler with save address handlers
- Updated MessageHandler to prompt for save preference on first use
User will only be asked once about saving addresses. Account reset clears preference.
- Removed informational 'Variants: Size: X options, Color: Y options' button
- Renamed 'Add to Cart' button to 'BUY {product.Name}' for clearer UX
- Applied to both multi-buy single item and regular quantity purchase buttons
## Critical Bug Fixes
### Currency Display (£ vs $)
- Fix MenuBuilder.cs: Replace $ with £ for product prices (line 60) and order totals (line 329)
- Fix ProductCarouselService.cs: Replace $ with £ in product captions and multi-buy offers (lines 317, 325)
- Fix CallbackHandler.cs: Replace $ with £ in order confirmation message (line 800)
### Payment Amount Display Bug
- Fix MessageFormatter.cs: Remove flawed crypto detection logic (< 1.0m check)
- Bug: Order for £700 in ETH displayed as "£1.66" instead of "1.66 ETH"
- Root cause: RequiredAmount is always stored as crypto amount, not fiat
- Solution: Always display RequiredAmount with crypto symbol
- Impact: Fixes display for XMR, DOGE, LTC, and large ETH amounts
## Security: Remove PGP Encryption Feature
### Critical Security Issue Resolved
- PGP "encryption" was only Base64 encoding - NOT real encryption
- Shipping addresses stored as easily decoded text
- False sense of security for users
### Changes Made
- Mark EncryptWithPGP method as [Obsolete] in PrivacyService.cs
- Remove PGP encryption logic from order creation (LittleShopService.cs)
- Mark PGP properties as [Obsolete] in UserSession.cs models
- Disable EnablePGPEncryption feature flag in appsettings.json
- Add comments explaining feature removal
### Recommendation
Implement proper PGP encryption using BouncyCastle in future, or keep removed.
## Testing Required
- Verify all prices display with £ symbol
- Verify crypto payments show correct amount format (e.g., "1.66000000 ETH")
- Verify no PGP options appear in UI
- Test order creation without PGP encryption
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- ProductCarouselService: Use Buy button with short IDs for products without images
- CallbackHandler: Fix HandleCategory to use Buy button with short IDs
- MenuBuilder: Remove obsolete SingleProductMenu method
This ensures consistent behavior across all product displays and fixes
the Details button that was broken due to GUID format incompatibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Issue**: Order creation failed because TOR proxy was being used for internal
Docker network API calls to littleshop-admin, causing DNS resolution failures.
**Root Cause**:
- All HTTP clients (BotManager, ActivityTracker, ProductCarousel) used
Socks5HttpHandler.Create() which checked Privacy:EnableTor globally
- TOR gateway can only proxy external traffic (to Telegram API)
- Internal Docker network calls to littleshop-admin failed through TOR
**Solution**:
- Updated BotManagerService to use Socks5HttpHandler.CreateDirect()
- Updated BotActivityTracker to use Socks5HttpHandler.CreateDirect()
- Updated ProductCarouselService to use Socks5HttpHandler.CreateDirect()
- TelegramBotService continues using TOR for external Telegram API
- LittleShop.Client respects LittleShop:UseTor = false setting
**Architecture**:
✅ External calls (Telegram API) → TOR for privacy
✅ Internal calls (LittleShop API) → Direct Docker network connection
**Testing**:
- Bot authenticated successfully with LittleShop API (200 OK)
- Telegram Bot API using TOR proxy (socks5://tor-gateway:9050)
- Container: 45eab050eeeca479680966b45742cf140cf7df0ed8e8ab5dc8c9e3e17739c88a
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Issue**: When users clicked "Browse Products" multiple times, Telegram API
rejected the edit request with "message is not modified" error, causing the
browse functionality to appear broken.
**Root Cause**: HandleBrowse method used EditMessageTextAsync directly, which
throws an exception when the message content is identical.
**Solution**:
- Replaced direct EditMessageTextAsync with SafeEditMessageAsync
- SafeEditMessageAsync catches ApiRequestException for "message is not modified"
- Silently handles duplicate edits without user-facing errors
**Testing**:
- Deployed to production (container: e1467c559ff6)
- Bot running as @Slukdevukbot with TOR enabled
- Categories API confirmed working (3 categories, 10 products)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Allows TOR proxy host to be configured via Privacy:TorSocksHost setting.
Defaults to 127.0.0.1 if not specified for backward compatibility.
This enables using external TOR gateways in Docker/container environments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
MaxAutomaticRedirections cannot be set to 0 in .NET 9.0. When AllowAutoRedirect
is false, the MaxAutomaticRedirections property should not be set at all.
This fixes the TeleBot TOR proxy configuration crash.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated .gitlab-ci.yml with complete build, test, and deploy stages
- Added authentication redirect fix in Program.cs (302 redirect for admin routes)
- Fixed Cookie vs Bearer authentication conflict for admin panel
- Configure pipeline to build from .NET 9.0 source
- Deploy to Hostinger VPS with proper environment variables
- Include rollback capability for production deployments
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces a comprehensive variant management system and enhances
the existing ProductVariant model with per-variant weight overrides and stock
tracking, integrated across Admin Panel and TeleBot.
Features Added:
- Variant Collections: Reusable variant templates (e.g., "Standard Sizes")
- Admin UI for managing variant collections (CRUD operations)
- Dynamic variant editor with JavaScript-based UI
- Per-variant weight and weight unit overrides
- Per-variant stock level tracking
- SalesLedger model for financial tracking
ProductVariant Enhancements:
- Added Weight (decimal, nullable) field for variant-specific weights
- Added WeightUnit (enum, nullable) field for variant-specific units
- Maintains backward compatibility with product-level weights
TeleBot Integration:
- Enhanced variant selection UI to display stock levels
- Shows weight information with proper unit conversion (µg, g, oz, lb, ml, L)
- Compact button format: "Medium (15 in stock, 350g)"
- Real-time stock availability display
Database Migrations:
- 20250928014850_AddVariantCollectionsAndSalesLedger
- 20250928155814_AddWeightToProductVariants
Technical Changes:
- Updated Product model to support VariantCollectionId and VariantsJson
- Extended ProductService with variant collection operations
- Enhanced OrderService to handle variant-specific pricing and weights
- Updated LittleShop.Client DTOs to match server models
- Added JavaScript dynamic variant form builder
Files Modified: 15
Files Added: 17
Lines Changed: ~2000
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created .gitlab-ci.yml for automated builds and deployment
- Added docker-compose.production.yml for VPS deployment
- Added .env.production.example for configuration template
- Follows LittleShop deployment pattern
- Auto-deploy on main branch commits
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated LittleShop API URL to use VPN hostname (hq.lan)
- Added Version 1.0.3 properties to project file
- Follows infrastructure changes with VPN-based access
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
FEATURES IMPLEMENTED:
1. Enhanced Product Display:
- Shows multi-buy deals with pricing (e.g., "3 for £25")
- Displays available variants grouped by type (Color, Flavor, etc.)
- Clear visual separation between multi-buys and variants
2. Variant Selection Flow:
- Single item: Select one variant from available options
- Multi-buy bundles: Select individual variants for each item
- Example: 3-pack allows choosing Red, Blue, Green individually
- Visual feedback with checkmarks and counters
3. Smart Cart Management:
- Tracks selected variants for each cart item
- Supports both single variant (regular items) and multiple variants (multi-buys)
- Unique cart entries based on product + variant combination
- Prevents duplicate multi-buy bundles
4. User Experience Improvements:
- Clear "Select Color/Flavor" prompts
- Progress indicator for multi-item selection
- Confirm button appears when selection complete
- Clear selection option for multi-buys
- Back navigation preserves context
TECHNICAL CHANGES:
- ProductCarouselService: Enhanced caption formatting with variants/multi-buys
- MenuBuilder: New VariantSelectionMenu with dynamic button generation
- CallbackHandler: Added handlers for selectvar, setvariant, addvariant, confirmvar
- ShoppingCart: New AddItem overload accepting Product and variant list
- CartItem: Added SelectedVariants list for multi-buy support
- UserSession: Added SelectingVariants state
This update enables customers to:
- See all available product options at a glance
- Choose specific variants when ordering
- Mix and match variants in multi-buy deals
- Get exactly what they want with clear visual feedback
Next steps: Add bot activity tracking for live dashboard
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed CryptoAmount property that doesn't exist
- Display £ amounts with note about needing conversion
- Show actual crypto amounts when less than 1.0
- Remove unnecessary shipping name step (Step 1/5) - now collects all address details in one message
- Fix currency display to show crypto amounts instead of GBP values
- Display proper BTC amounts instead of showing £39.99 as 39.99 BTC
- Tor connectivity already working (verified via telebot-tor container)
- Add reviews section with /reviews command and menu button
- Fix /delete command to include main menu after deletion
- Remove unused commands (tor, ephemeral, pgpkey) from help
- Remove 'Products with Images' button from main menu
- Update main menu: rename Browse to 'Browse Products', add Reviews button
- Add placeholder reviews display handler (TODO: fetch from API)
- Clean up help text to reflect actual available commands
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix admin panel to show all pending orders (PendingPayment + PaymentReceived)
- Fix currency display from USD ($) to GBP (£) throughout TeleBot
- Update payment methods to use dynamic SilverPay currency list
- Consolidate shipping address collection into single message
- Implement cart backup/restore on payment failure
- Remove unsupported XMR from TeleBot config
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major restructuring of product variations:
- Renamed ProductVariation to ProductMultiBuy for quantity-based pricing (e.g., "3 for £25")
- Added new ProductVariant model for string-based options (colors, flavors)
- Complete separation of multi-buy pricing from variant selection
Features implemented:
- Multi-buy deals with automatic price-per-unit calculation
- Product variants for colors/flavors/sizes with stock tracking
- TeleBot checkout supports both multi-buys and variant selection
- Shopping cart correctly calculates multi-buy bundle prices
- Order system tracks selected variants and multi-buy choices
- Real-time bot activity monitoring with SignalR
- Public bot directory page with QR codes for Telegram launch
- Admin dashboard shows multi-buy and variant metrics
Technical changes:
- Updated all DTOs, services, and controllers
- Fixed cart total calculation for multi-buy bundles
- Comprehensive test coverage for new functionality
- All existing tests passing with new features
Database changes:
- Migrated ProductVariations to ProductMultiBuys
- Added ProductVariants table
- Updated OrderItems to track variants
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed all BTCPay references from services and configuration
- Implemented SilverPAY as sole payment provider (no fallback)
- Fixed JWT authentication with proper key length (256+ bits)
- Added UsersController with full CRUD operations
- Updated User model with Email and Role properties
- Configured TeleBot with real Telegram bot token
- Fixed launchSettings.json with JWT environment variable
- E2E tests passing for authentication, catalog, orders
- Payment creation pending SilverPAY server fix
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Add admin PWA push notifications for order management
- Integrate TeleBot customer messaging service
- Add push notification endpoints and VAPID key support
- Implement order status notifications throughout workflow
- Add notification UI components in admin panel
- Create TeleBotMessagingService for customer updates
- Add WebPush configuration to appsettings
- Fix compilation issues (BotStatus, BotContacts DbSet)
- Add comprehensive testing documentation
Features:
- Real-time admin notifications for new orders and status changes
- Customer order progress updates via TeleBot
- Graceful failure handling for notification services
- Test endpoints for notification system validation
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Set up Tor container for SOCKS proxy (port 9050)
- Configured Monero wallet with remote onion node
- Bitcoin node continues syncing in background (60% complete)
- Created documentation for wallet configuration steps
- All external connections routed through Tor for privacy
BTCPay requires manual wallet configuration through web interface:
- Bitcoin: Need to add xpub/zpub for watch-only wallet
- Monero: Need to add address and view key
System ready for payment acceptance once wallets configured.