From 947092ce545870210ca20e31263df7840702b1c2 Mon Sep 17 00:00:00 2001 From: Dylan Knutson Date: Wed, 27 Aug 2025 02:57:14 +0000 Subject: [PATCH] add README.md --- README.md | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a6c679 --- /dev/null +++ b/README.md @@ -0,0 +1,351 @@ +# Telegram Auction Bot - Complete Project Specification + +## Project Overview + +A Telegram bot for managing various types of auctions, built in Rust using SQLite as the backend database. The bot facilitates auctions between sellers and buyers without handling payments directly. + +## Core Features + +### Auction Types +1. **Standard Auctions**: Traditional time-based bidding with anti-sniping protection +2. **Multi-slot Auctions**: Multiple winners (e.g., 3 commission slots available) +3. **Fixed Price Sales**: Set price with limited quantity +4. **Blind Auctions**: Bidders submit amounts with descriptions; seller chooses winner (not necessarily highest bid) + +### Key Functionality +- **Telegram Bot**: The bot is interacted with primarily through Telegram. Sellers can create auctions, and view bids on auctions. Buyers can bid on auctions and view their bids. +- **Proxy/Automatic Bidding**: Users set maximum bid; system auto-bids up to that amount +- **Anti-sniping Protection**: Configurable time extension if bid placed in last N minutes +- **Buy-now Option**: Instant purchase at fixed price +- **Media Support**: Multiple images/videos per auction on the telegram post. +- **Outbid Notifications**: Configurable user notifications +- **Non-payment Handling**: Track failed payments, allow selection of next highest bidder +- **Localization Support**: Multi-language structure (to be implemented) +- **Admin Interface**: Separate web interface for moderation (to be implemented) + +## Database Schema (SQLite) + +```sql +-- Core user tracking +CREATE TABLE users ( + id INTEGER PRIMARY KEY, + telegram_id INTEGER UNIQUE NOT NULL, + username TEXT, + display_name TEXT, + is_banned BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Main auction table (handles all auction types) +CREATE TABLE auctions ( + id INTEGER PRIMARY KEY, + seller_id INTEGER NOT NULL, + auction_type TEXT NOT NULL, -- 'standard', 'multi_slot', 'fixed_price', 'blind' + title TEXT NOT NULL, + description TEXT, + + -- Pricing + starting_bid DECIMAL(10,2), + buy_now_price DECIMAL(10,2), + min_increment DECIMAL(10,2) DEFAULT 1.00, + + -- Multi-slot/fixed price + slots_available INTEGER DEFAULT 1, + + -- Timing + starts_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + ends_at TIMESTAMP NOT NULL, + anti_snipe_minutes INTEGER DEFAULT 5, + + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (seller_id) REFERENCES users(id) +); + +-- Proxy bid strategies (NOT actual bids, but bidding strategies) +CREATE TABLE proxy_bids ( + id INTEGER PRIMARY KEY, + auction_id INTEGER NOT NULL, + buyer_id INTEGER NOT NULL, + max_amount DECIMAL(10,2) NOT NULL, + is_active BOOLEAN DEFAULT TRUE, + + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + FOREIGN KEY (auction_id) REFERENCES auctions(id), + FOREIGN KEY (buyer_id) REFERENCES users(id), + UNIQUE(auction_id, buyer_id) -- One active proxy per user per auction +); + +-- Actual bids that happened (events) +CREATE TABLE bids ( + id INTEGER PRIMARY KEY, + auction_id INTEGER NOT NULL, + buyer_id INTEGER NOT NULL, + bid_amount DECIMAL(10,2) NOT NULL, + + -- For blind auctions + description TEXT, + + -- Status + is_cancelled BOOLEAN DEFAULT FALSE, + slot_number INTEGER, -- For multi-slot auctions + + -- NULL = manual bid, NOT NULL = generated from proxy + proxy_bid_id INTEGER, + + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (auction_id) REFERENCES auctions(id), + FOREIGN KEY (buyer_id) REFERENCES users(id), + FOREIGN KEY (proxy_bid_id) REFERENCES proxy_bids(id) +); + +-- Media attachments +CREATE TABLE auction_medias ( + id INTEGER PRIMARY KEY, + auction_id INTEGER NOT NULL, + telegram_file_id TEXT NOT NULL, + media_type TEXT NOT NULL, -- 'photo', 'video' + position INTEGER DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (auction_id) REFERENCES auctions(id) +); + +-- User preferences +CREATE TABLE user_settings ( + user_id INTEGER PRIMARY KEY, + language_code TEXT DEFAULT 'en', + notify_outbid BOOLEAN DEFAULT TRUE, + notify_won BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) +); +``` + +## Key Design Decisions + +### 1. Proxy Bid Architecture +- **Proxy bids** are stored as strategies in `proxy_bids` table +- **Actual bids** are events stored in `bids` table +- When a bid is placed, system checks for proxy bids and generates actual bids +- `proxy_bid_id` in bids table is NULL for manual bids, references proxy for auto-generated + +### 2. Database Normalization +- No redundant data - everything computed from source +- Winning bid inferred from highest non-cancelled bid +- Last proxy bid amount inferred from bids with that proxy_bid_id + +### 3. Multi-slot Auctions +- Single auction with `slots_available > 1` +- Top N bids win (where N = slots_available) +- Each winning bid gets a slot_number + +## Project Structure + +``` +auction-bot/ +├── Cargo.toml # Dependencies +├── .env # Environment variables (create from .env.example) +├── migrations/ # SQL migrations +│ └── 001_initial_schema.sql +└── src/ + └── main.rs # Entry point, bot setup, command router +``` + +## Current Implementation Status + +### ❌ Not Yet Implemented +- Auction creation flow +- Media upload handling +- Bidding flow +- Settings management +- Proxy bidding logic +- Anti-snipe detection and time extension +- Notification system +- Tasks for auction expiry, scheduled to run when the auction ends +- Admin web interface (separate from the bot, uses the same database) +- Auction browsing with pagination +- Bid history viewing +- Localization/i18n + +## Critical Implementation Details + +### Proxy Bidding Logic +```rust +// When a new bid is placed: +// 1. Insert the actual bid +// 2. Find all active proxy bids for this auction (except current bidder) +// 3. For each proxy that can beat the new bid: +// - Generate actual bid = current_bid + min_increment +// - Update proxy's last generated bid +// - Only one proxy responds per bid event + +// When proxy bid is created/updated: +// 1. Upsert proxy bid strategy +// 2. Check current winning bid +// 3. If can beat it, generate immediate bid +``` + +### Anti-Snipe Logic +```rust +// On each bid: +// 1. auction.ends_at = MAX(auction.ends_at, now + anti_snipe_minutes) +// 2. Notify users of time extension if there was one +``` + +### Auction State Management +- Consider using `HashMap` for in-memory draft storage +- Or create `auction_drafts` table for persistence across bot restarts + +### Background Tasks Needed +1. **Auction Expiry Checker** (every 30 seconds) + - Find auctions where `ends_at < now AND is_active = true` + - Mark as inactive + - Create winner records + - Send notifications + +2. **Notification Dispatcher** (every 10 seconds) + - Check notification queue + - Batch send to avoid rate limits + - Handle outbid, win, and reminder notifications + +## Environment Variables (.env) + +```bash +# Required +TELOXIDE_TOKEN=your_bot_token_here +DATABASE_URL=sqlite:pawctioneer_bot.db + +# Optional +RUST_LOG=info,pawctioneer_bot=debug +ADMIN_USER_ID=your_telegram_user_id +WEB_PORT=3000 # For future admin interface +TZ=UTC +``` + +## Bot Commands (Set in BotFather) + +``` +start - Show welcome message +help - Show help message +newauction - Create a new auction +myauctions - View your auctions as a seller +mybids - View your active bids +settings - Configure notifications +``` + +## Dependencies Rationale + +- **teloxide**: Modern Telegram bot framework with good ergonomics +- **sqlx**: Compile-time checked SQL queries, async support +- **tokio**: Industry standard async runtime +- **rust_decimal**: Proper decimal handling for money +- **chrono**: Timezone-aware datetime handling + +## Next Implementation Steps (Priority Order) + +### 1. Complete Auction Creation Flow +- Implement multi-step wizard state machine +- Handle media uploads (store Telegram file_ids) +- Add validation for each field +- Create auction in database + +### 2. Implement Bidding System +- Place manual bid function +- Proxy bid creation and processing +- Bid validation (minimum amounts, increment checks) +- Update auction message after each bid + +### 3. Add Background Tasks +- Tokio spawn for periodic tasks +- Auction expiry processing +- Notification sending + +### 4. Auction Browsing +- Paginated list with filters +- Search functionality +- Detailed auction view with bid history + +### 5. Admin Interface +- Axum web server in same binary +- Dashboard with stats +- User management (bans, warnings) +- Auction moderation tools + +## Common SQL Queries Needed + +```sql +-- Get current winning bid for standard auction +SELECT b.*, u.username +FROM bids b +JOIN users u ON b.user_id = u.id +WHERE b.auction_id = ? + AND b.is_cancelled = FALSE +ORDER BY b.bid_amount DESC +LIMIT 1; + +-- Get winning bids for multi-slot auction +SELECT b.*, u.username +FROM bids b +JOIN users u ON b.user_id = u.id +WHERE b.auction_id = ? + AND b.is_cancelled = FALSE +ORDER BY b.bid_amount DESC +LIMIT ?; -- slots_available + +-- Check if bid was auto-generated +SELECT *, (proxy_bid_id IS NOT NULL) as is_proxy_generated +FROM bids WHERE id = ?; + +-- Get active proxy bids for an auction +SELECT * FROM proxy_bids +WHERE auction_id = ? AND is_active = TRUE; + +-- Get user's current proxy bid with last generated amount +SELECT + p.*, + b.bid_amount as last_bid_amount +FROM proxy_bids p +LEFT JOIN bids b ON b.proxy_bid_id = p.id +WHERE p.auction_id = ? AND p.user_id = ? AND p.is_active = TRUE +ORDER BY b.created_at DESC +LIMIT 1; +``` + +## Testing Checklist + +- [ ] User registration on first interaction +- [ ] Auction creation (all types) +- [ ] Manual bidding +- [ ] Proxy bidding with conflicts +- [ ] Anti-snipe time extension +- [ ] Buy-now purchase +- [ ] Multi-slot auction with multiple winners +- [ ] Blind auction with description +- [ ] Non-payment flow +- [ ] User ban system +- [ ] Notification delivery +- [ ] Media upload and display + +## Deployment Notes + +- Use systemd service for production +- Set up automatic restarts +- Configure log rotation +- Use separate database file for production +- Regular database backups +- Monitor Telegram API rate limits + +## API Rate Limits to Consider + +- Telegram allows 30 messages/second to different users +- 20 messages/minute to same user +- Bulk notifications should be queued and throttled +- Edit message updates should be debounced + +This README contains the complete context of the project. All design decisions have been made, the schema is finalized, and the basic structure is in place. The next step is implementing the core business logic for auctions and bidding. \ No newline at end of file