Files
pawctioneer-bot/README.md
2025-08-27 19:12:40 +00:00

350 lines
11 KiB
Markdown

# 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<user_id, AuctionDraft>` 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
## 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.