first commit
This commit is contained in:
987
MULTI_BOT_SETUP.md
Normal file
987
MULTI_BOT_SETUP.md
Normal file
@@ -0,0 +1,987 @@
|
||||
# Multi-Bot Setup with Proxies & Verification Codes
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
TurboTrades now supports **multiple Steam bots** with:
|
||||
- ✅ **Load Balancing** - Automatically distributes trades across bots
|
||||
- ✅ **Proxy Support** - Each bot can use different proxy (SOCKS5/HTTP)
|
||||
- ✅ **Verification Codes** - 6-digit codes shown on site and in trade
|
||||
- ✅ **Automatic Failover** - If one bot fails, others take over
|
||||
- ✅ **Health Monitoring** - Track bot status and performance
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Why Verification Codes?
|
||||
|
||||
**Security Feature**: Prevents scam bots from impersonating your trade offers.
|
||||
|
||||
**How it works:**
|
||||
1. User clicks "Sell Items" on website
|
||||
2. System generates unique 6-digit code (e.g., `A3K9P2`)
|
||||
3. Code is shown prominently on website
|
||||
4. Same code is included in Steam trade offer message
|
||||
5. User **MUST verify** code matches before accepting
|
||||
|
||||
**Benefits:**
|
||||
- ✅ User can verify trade is legitimate
|
||||
- ✅ Prevents phishing/fake trade offers
|
||||
- ✅ Adds extra layer of security
|
||||
- ✅ Easy to implement and understand
|
||||
|
||||
---
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
### For Each Bot Account:
|
||||
|
||||
1. **Separate Steam Account**
|
||||
- Not your personal account!
|
||||
- Must have spent $5+ (not limited)
|
||||
- Public inventory
|
||||
- Valid trade URL
|
||||
|
||||
2. **Steam Mobile Authenticator**
|
||||
- Enabled on each bot account
|
||||
- Trade cooldown period expired (7 days)
|
||||
|
||||
3. **Shared Secret & Identity Secret**
|
||||
- Extract using SDA (Steam Desktop Authenticator)
|
||||
- Or use mobile app extraction tools
|
||||
|
||||
4. **Steam API Key**
|
||||
- Get from: https://steamcommunity.com/dev/apikey
|
||||
- Can use same API key for all bots
|
||||
|
||||
5. **Proxy (Optional but Recommended)**
|
||||
- SOCKS5 or HTTP/HTTPS proxy
|
||||
- One proxy per bot
|
||||
- Prevents IP rate limiting
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Bot Configuration
|
||||
|
||||
### Configuration File Format
|
||||
|
||||
Create `config/steam-bots.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"bots": [
|
||||
{
|
||||
"accountName": "turbobot_01",
|
||||
"password": "secure_password_1",
|
||||
"sharedSecret": "abcdef1234567890",
|
||||
"identitySecret": "xyz9876543210abc",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY",
|
||||
"proxy": {
|
||||
"type": "socks5",
|
||||
"host": "proxy1.example.com",
|
||||
"port": 1080,
|
||||
"username": "proxy_user",
|
||||
"password": "proxy_pass"
|
||||
},
|
||||
"maxConcurrentTrades": 10,
|
||||
"pollInterval": 30000,
|
||||
"tradeTimeout": 600000
|
||||
},
|
||||
{
|
||||
"accountName": "turbobot_02",
|
||||
"password": "secure_password_2",
|
||||
"sharedSecret": "fedcba0987654321",
|
||||
"identitySecret": "cba0123456789xyz",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY",
|
||||
"proxy": {
|
||||
"type": "http",
|
||||
"host": "proxy2.example.com",
|
||||
"port": 8080,
|
||||
"username": "proxy_user2",
|
||||
"password": "proxy_pass2"
|
||||
},
|
||||
"maxConcurrentTrades": 10,
|
||||
"pollInterval": 30000,
|
||||
"tradeTimeout": 600000
|
||||
},
|
||||
{
|
||||
"accountName": "turbobot_03",
|
||||
"password": "secure_password_3",
|
||||
"sharedSecret": "1234567890abcdef",
|
||||
"identitySecret": "0987654321zyxwvu",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY",
|
||||
"proxy": null,
|
||||
"maxConcurrentTrades": 10,
|
||||
"pollInterval": 30000,
|
||||
"tradeTimeout": 600000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Environment Variables (Alternative)
|
||||
|
||||
Or use environment variables:
|
||||
|
||||
```env
|
||||
# Bot 1
|
||||
STEAM_BOT_1_USERNAME=turbobot_01
|
||||
STEAM_BOT_1_PASSWORD=secure_password_1
|
||||
STEAM_BOT_1_SHARED_SECRET=abcdef1234567890
|
||||
STEAM_BOT_1_IDENTITY_SECRET=xyz9876543210abc
|
||||
STEAM_BOT_1_PROXY=socks5://user:pass@proxy1.example.com:1080
|
||||
|
||||
# Bot 2
|
||||
STEAM_BOT_2_USERNAME=turbobot_02
|
||||
STEAM_BOT_2_PASSWORD=secure_password_2
|
||||
STEAM_BOT_2_SHARED_SECRET=fedcba0987654321
|
||||
STEAM_BOT_2_IDENTITY_SECRET=cba0123456789xyz
|
||||
STEAM_BOT_2_PROXY=http://user2:pass2@proxy2.example.com:8080
|
||||
|
||||
# Bot 3
|
||||
STEAM_BOT_3_USERNAME=turbobot_03
|
||||
STEAM_BOT_3_PASSWORD=secure_password_3
|
||||
STEAM_BOT_3_SHARED_SECRET=1234567890abcdef
|
||||
STEAM_BOT_3_IDENTITY_SECRET=0987654321zyxwvu
|
||||
# No proxy for bot 3
|
||||
|
||||
# Global Settings
|
||||
STEAM_API_KEY=YOUR_STEAM_API_KEY
|
||||
STEAM_BOT_COUNT=3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Proxy Configuration
|
||||
|
||||
### Why Use Proxies?
|
||||
|
||||
- ✅ **Prevent Rate Limiting** - Each bot has own IP
|
||||
- ✅ **Geographic Distribution** - Bots appear from different locations
|
||||
- ✅ **Avoid Bans** - If one IP gets rate limited, others continue
|
||||
- ✅ **Better Performance** - Distribute load across proxies
|
||||
|
||||
### Proxy Types Supported
|
||||
|
||||
#### 1. SOCKS5 (Recommended)
|
||||
```json
|
||||
{
|
||||
"type": "socks5",
|
||||
"host": "proxy.example.com",
|
||||
"port": 1080,
|
||||
"username": "user",
|
||||
"password": "pass"
|
||||
}
|
||||
```
|
||||
|
||||
**Best for:**
|
||||
- Steam connections
|
||||
- High performance
|
||||
- Full protocol support
|
||||
|
||||
#### 2. HTTP/HTTPS
|
||||
```json
|
||||
{
|
||||
"type": "http",
|
||||
"host": "proxy.example.com",
|
||||
"port": 8080,
|
||||
"username": "user",
|
||||
"password": "pass"
|
||||
}
|
||||
```
|
||||
|
||||
**Best for:**
|
||||
- Web requests
|
||||
- Simple setup
|
||||
- Most proxy providers
|
||||
|
||||
#### 3. No Proxy
|
||||
```json
|
||||
{
|
||||
"proxy": null
|
||||
}
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Testing locally
|
||||
- VPS with good IP reputation
|
||||
- Low trade volume
|
||||
|
||||
### Proxy Providers
|
||||
|
||||
**Recommended Providers:**
|
||||
- **Bright Data** (formerly Luminati) - Premium, reliable
|
||||
- **Oxylabs** - High quality, expensive
|
||||
- **IPRoyal** - Good balance of price/quality
|
||||
- **Webshare** - Budget friendly
|
||||
- **SmartProxy** - Good for Steam
|
||||
|
||||
**Requirements:**
|
||||
- Dedicated or semi-dedicated IPs
|
||||
- SOCKS5 support preferred
|
||||
- Good uptime (99%+)
|
||||
- Reasonable speed (<500ms latency)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Starting Multiple Bots
|
||||
|
||||
### Method 1: Using Configuration File
|
||||
|
||||
```javascript
|
||||
// index.js or startup file
|
||||
import { getSteamBotManager } from './services/steamBot.js';
|
||||
import botsConfig from './config/steam-bots.json' assert { type: 'json' };
|
||||
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Initialize all bots
|
||||
await botManager.initialize(botsConfig.bots);
|
||||
|
||||
console.log('✅ All bots initialized');
|
||||
```
|
||||
|
||||
### Method 2: Using Environment Variables
|
||||
|
||||
```javascript
|
||||
import { getSteamBotManager } from './services/steamBot.js';
|
||||
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Build config from environment
|
||||
const botsConfig = [];
|
||||
const botCount = parseInt(process.env.STEAM_BOT_COUNT || '1');
|
||||
|
||||
for (let i = 1; i <= botCount; i++) {
|
||||
const prefix = `STEAM_BOT_${i}_`;
|
||||
|
||||
if (!process.env[prefix + 'USERNAME']) continue;
|
||||
|
||||
botsConfig.push({
|
||||
accountName: process.env[prefix + 'USERNAME'],
|
||||
password: process.env[prefix + 'PASSWORD'],
|
||||
sharedSecret: process.env[prefix + 'SHARED_SECRET'],
|
||||
identitySecret: process.env[prefix + 'IDENTITY_SECRET'],
|
||||
steamApiKey: process.env.STEAM_API_KEY,
|
||||
proxy: process.env[prefix + 'PROXY']
|
||||
? parseProxyUrl(process.env[prefix + 'PROXY'])
|
||||
: null,
|
||||
});
|
||||
}
|
||||
|
||||
await botManager.initialize(botsConfig);
|
||||
```
|
||||
|
||||
### Method 3: Auto-Start on Backend Launch
|
||||
|
||||
```javascript
|
||||
// In your main server file
|
||||
import { getSteamBotManager } from './services/steamBot.js';
|
||||
|
||||
// After fastify.listen()
|
||||
if (process.env.STEAM_BOT_AUTO_START === 'true') {
|
||||
console.log('🤖 Auto-starting Steam bots...');
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Load config
|
||||
const botsConfig = loadBotsConfig(); // Your config loading logic
|
||||
|
||||
await botManager.initialize(botsConfig);
|
||||
|
||||
console.log('✅ Steam bots ready');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Creating Trades with Verification Codes
|
||||
|
||||
### Backend Example
|
||||
|
||||
```javascript
|
||||
import { getSteamBotManager } from '../services/steamBot.js';
|
||||
import Trade from '../models/Trade.js';
|
||||
|
||||
// User sells items
|
||||
fastify.post('/api/trade/create', async (request, reply) => {
|
||||
const { items } = request.body;
|
||||
const userId = request.user._id;
|
||||
const steamId = request.user.steamId;
|
||||
const tradeUrl = request.user.tradeUrl;
|
||||
|
||||
// Calculate values
|
||||
const totalValue = items.reduce((sum, item) => sum + item.price, 0);
|
||||
const fee = totalValue * 0.05; // 5% fee
|
||||
const userReceives = totalValue - fee;
|
||||
|
||||
// Create trade offer with automatic bot selection
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
const result = await botManager.createTradeOffer({
|
||||
tradeUrl: tradeUrl,
|
||||
itemsToReceive: items.map(item => ({
|
||||
assetid: item.assetId,
|
||||
appid: 730, // CS2
|
||||
contextid: 2
|
||||
})),
|
||||
userId: userId,
|
||||
metadata: {
|
||||
itemCount: items.length,
|
||||
totalValue: totalValue
|
||||
}
|
||||
});
|
||||
|
||||
// Create trade record in database
|
||||
const trade = await Trade.createTrade({
|
||||
offerId: result.offerId,
|
||||
userId: userId,
|
||||
steamId: steamId,
|
||||
state: 'pending',
|
||||
items: items,
|
||||
totalValue: totalValue,
|
||||
fee: fee,
|
||||
feePercentage: 5,
|
||||
userReceives: userReceives,
|
||||
tradeUrl: tradeUrl,
|
||||
verificationCode: result.verificationCode,
|
||||
botId: result.botId,
|
||||
expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
|
||||
sessionId: request.session?.id,
|
||||
});
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
trade: {
|
||||
id: trade._id,
|
||||
offerId: trade.offerId,
|
||||
verificationCode: trade.verificationCode, // ⭐ IMPORTANT: Show to user
|
||||
state: 'pending',
|
||||
totalValue: totalValue,
|
||||
userReceives: userReceives,
|
||||
expiresAt: trade.expiresAt,
|
||||
message: 'Trade offer sent! Please check your Steam app.'
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### What User Sees on Website
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ Trade Offer Sent! │
|
||||
├────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Verification Code: │
|
||||
│ ┏━━━━━━━━━━━━━━━┓ │
|
||||
│ ┃ A 3 K 9 P 2 ┃ <- Large, clear │
|
||||
│ ┗━━━━━━━━━━━━━━━┛ │
|
||||
│ │
|
||||
│ ⚠️ IMPORTANT: │
|
||||
│ Check that this code appears in your │
|
||||
│ Steam trade offer. DO NOT accept trades │
|
||||
│ without this code! │
|
||||
│ │
|
||||
│ Status: Waiting for acceptance... │
|
||||
│ Expires in: 9:45 │
|
||||
│ │
|
||||
│ [View in Steam] [Cancel Trade] │
|
||||
│ │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### What User Sees in Steam Trade Offer
|
||||
|
||||
```
|
||||
Trade Offer from turbobot_01
|
||||
|
||||
TurboTrades Trade
|
||||
Verification Code: A3K9P2
|
||||
|
||||
Please verify this code matches the one shown
|
||||
on our website before accepting.
|
||||
|
||||
Do not accept trades without a valid
|
||||
verification code!
|
||||
|
||||
You will receive:
|
||||
- Nothing
|
||||
|
||||
You will give:
|
||||
- AK-47 | Redline (Field-Tested)
|
||||
- AWP | Asiimov (Battle-Scarred)
|
||||
|
||||
[Accept] [Decline]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Load Balancing
|
||||
|
||||
### How Bot Selection Works
|
||||
|
||||
1. **Filter Available Bots**
|
||||
- Must be logged in
|
||||
- Must be healthy (low error count)
|
||||
- Must have capacity (< max concurrent trades)
|
||||
|
||||
2. **Sort by Load**
|
||||
- Bots with fewer active trades ranked higher
|
||||
- Distributes load evenly
|
||||
|
||||
3. **Select Best Bot**
|
||||
- Returns bot with lowest current load
|
||||
- If all bots busy, throws error
|
||||
|
||||
### Example Load Distribution
|
||||
|
||||
```
|
||||
Bot 1: 3 active trades <- Selected (lowest)
|
||||
Bot 2: 5 active trades
|
||||
Bot 3: 7 active trades
|
||||
|
||||
Next trade goes to Bot 1
|
||||
|
||||
After assignment:
|
||||
Bot 1: 4 active trades
|
||||
Bot 2: 5 active trades <- Next trade goes here
|
||||
Bot 3: 7 active trades
|
||||
```
|
||||
|
||||
### Manual Bot Selection (Advanced)
|
||||
|
||||
```javascript
|
||||
// Get specific bot
|
||||
const bot = botManager.getBot('bot_1');
|
||||
|
||||
// Create trade with specific bot
|
||||
const result = await bot.createTradeOffer({
|
||||
tradeUrl: userTradeUrl,
|
||||
itemsToReceive: items,
|
||||
verificationCode: 'MANUAL1',
|
||||
metadata: {}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring & Health
|
||||
|
||||
### Check Bot Health
|
||||
|
||||
```javascript
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Get all bots health
|
||||
const health = botManager.getAllBotsHealth();
|
||||
console.log(health);
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"botId": "bot_1",
|
||||
"isReady": true,
|
||||
"isLoggedIn": true,
|
||||
"isHealthy": true,
|
||||
"activeTrades": 3,
|
||||
"tradeCount": 150,
|
||||
"errorCount": 2,
|
||||
"lastTradeTime": "2024-01-10T12:05:00Z",
|
||||
"username": "turbobot_01",
|
||||
"proxy": "socks5://proxy1.example.com:1080"
|
||||
},
|
||||
{
|
||||
"botId": "bot_2",
|
||||
"isReady": true,
|
||||
"isLoggedIn": true,
|
||||
"isHealthy": true,
|
||||
"activeTrades": 5,
|
||||
"tradeCount": 180,
|
||||
"errorCount": 1,
|
||||
"lastTradeTime": "2024-01-10T12:03:00Z",
|
||||
"username": "turbobot_02",
|
||||
"proxy": "http://proxy2.example.com:8080"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### System-Wide Stats
|
||||
|
||||
```javascript
|
||||
const stats = botManager.getStats();
|
||||
console.log(stats);
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```json
|
||||
{
|
||||
"totalBots": 3,
|
||||
"readyBots": 3,
|
||||
"healthyBots": 3,
|
||||
"totalTrades": 450,
|
||||
"totalActiveTrades": 12,
|
||||
"totalErrors": 5,
|
||||
"verificationCodesStored": 12
|
||||
}
|
||||
```
|
||||
|
||||
### Admin Dashboard Integration
|
||||
|
||||
Add to admin panel:
|
||||
|
||||
```javascript
|
||||
// GET /api/admin/bots/health
|
||||
fastify.get('/admin/bots/health', async (request, reply) => {
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
bots: botManager.getAllBotsHealth(),
|
||||
stats: botManager.getStats()
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Trade Events
|
||||
|
||||
### Listen to Trade Events
|
||||
|
||||
```javascript
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Trade accepted - Credit user balance!
|
||||
botManager.on('tradeAccepted', async (offer, tradeData, botId) => {
|
||||
console.log(`✅ Trade ${offer.id} accepted on ${botId}`);
|
||||
|
||||
const trade = await Trade.getByOfferId(offer.id);
|
||||
const user = await User.findById(trade.userId);
|
||||
|
||||
// Credit user balance
|
||||
user.balance += trade.userReceives;
|
||||
await user.save();
|
||||
|
||||
// Create transaction
|
||||
const transaction = await Transaction.createTransaction({
|
||||
userId: trade.userId,
|
||||
steamId: trade.steamId,
|
||||
type: 'sale',
|
||||
status: 'completed',
|
||||
amount: trade.userReceives,
|
||||
fee: trade.fee,
|
||||
feePercentage: trade.feePercentage,
|
||||
balanceBefore: user.balance - trade.userReceives,
|
||||
balanceAfter: user.balance,
|
||||
metadata: {
|
||||
tradeId: trade._id,
|
||||
offerId: trade.offerId,
|
||||
itemCount: trade.items.length
|
||||
}
|
||||
});
|
||||
|
||||
// Update trade
|
||||
await trade.markAsCompleted(transaction._id);
|
||||
|
||||
// Notify user via WebSocket
|
||||
websocketManager.sendToUser(trade.steamId, {
|
||||
type: 'trade_accepted',
|
||||
data: {
|
||||
tradeId: trade._id,
|
||||
balance: user.balance,
|
||||
amount: trade.userReceives
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Trade declined
|
||||
botManager.on('tradeDeclined', async (offer, tradeData, botId) => {
|
||||
console.log(`❌ Trade ${offer.id} declined on ${botId}`);
|
||||
|
||||
const trade = await Trade.getByOfferId(offer.id);
|
||||
await trade.markAsDeclined();
|
||||
|
||||
// Notify user
|
||||
websocketManager.sendToUser(trade.steamId, {
|
||||
type: 'trade_declined',
|
||||
data: {
|
||||
tradeId: trade._id,
|
||||
message: 'Trade offer was declined'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Trade expired
|
||||
botManager.on('tradeExpired', async (offer, tradeData, botId) => {
|
||||
console.log(`⏰ Trade ${offer.id} expired on ${botId}`);
|
||||
|
||||
const trade = await Trade.getByOfferId(offer.id);
|
||||
await trade.markAsExpired();
|
||||
|
||||
// Optionally retry
|
||||
if (trade.retryCount < 3) {
|
||||
console.log('🔄 Retrying expired trade...');
|
||||
// Retry logic here
|
||||
}
|
||||
});
|
||||
|
||||
// Bot error
|
||||
botManager.on('botError', (err, botId) => {
|
||||
console.error(`❌ Bot ${botId} error:`, err.message);
|
||||
|
||||
// Send alert to admins
|
||||
// Log to monitoring service
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Best Practices
|
||||
|
||||
### 1. Secure Credentials
|
||||
|
||||
```env
|
||||
# ✅ Good - Use environment variables
|
||||
STEAM_BOT_1_PASSWORD=secure_password
|
||||
|
||||
# ❌ Bad - Never hardcode in config files
|
||||
"password": "my_password_123"
|
||||
```
|
||||
|
||||
### 2. Rotate Proxies
|
||||
|
||||
- Change proxies monthly
|
||||
- Use different proxy providers
|
||||
- Monitor proxy performance
|
||||
- Replace slow/banned proxies
|
||||
|
||||
### 3. Bot Account Security
|
||||
|
||||
- ✅ Use unique passwords for each bot
|
||||
- ✅ Enable Steam Guard on all bots
|
||||
- ✅ Don't share bot accounts
|
||||
- ✅ Keep secrets in secure vault
|
||||
- ✅ Use 2FA on bot accounts
|
||||
|
||||
### 4. Verification Code Validation
|
||||
|
||||
```javascript
|
||||
// Always verify code before crediting balance
|
||||
const isValid = botManager.verifyTradeCode(offerId, userEnteredCode);
|
||||
if (!isValid) {
|
||||
throw new Error('Invalid verification code');
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Rate Limiting
|
||||
|
||||
```javascript
|
||||
// Limit trades per user per hour
|
||||
const userTrades = await Trade.find({
|
||||
userId: userId,
|
||||
createdAt: { $gte: new Date(Date.now() - 60 * 60 * 1000) }
|
||||
});
|
||||
|
||||
if (userTrades.length >= 10) {
|
||||
throw new Error('Trade limit exceeded. Try again later.');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Bot Won't Login
|
||||
|
||||
**Symptoms:**
|
||||
- Bot stuck at "Logging in..."
|
||||
- Error: "Invalid credentials"
|
||||
- Error: "SteamGuardMobile needed"
|
||||
|
||||
**Solutions:**
|
||||
1. Check credentials are correct
|
||||
2. Verify shared secret is valid
|
||||
3. Disable proxy temporarily to test
|
||||
4. Check Steam is not under maintenance
|
||||
5. Verify bot account not limited/banned
|
||||
|
||||
### Proxy Connection Failed
|
||||
|
||||
**Symptoms:**
|
||||
- Bot disconnects frequently
|
||||
- Error: "ECONNREFUSED"
|
||||
- Error: "Proxy authentication failed"
|
||||
|
||||
**Solutions:**
|
||||
1. Test proxy with curl:
|
||||
```bash
|
||||
curl -x socks5://user:pass@proxy:1080 https://steamcommunity.com
|
||||
```
|
||||
2. Verify proxy credentials
|
||||
3. Check proxy IP not banned by Steam
|
||||
4. Try different proxy
|
||||
5. Contact proxy provider
|
||||
|
||||
### Verification Codes Not Showing
|
||||
|
||||
**Symptoms:**
|
||||
- Trade offer created but no code
|
||||
- Code is null/undefined
|
||||
|
||||
**Solutions:**
|
||||
1. Check `verificationCode` saved in database
|
||||
2. Verify frontend is receiving code
|
||||
3. Check trade creation response
|
||||
4. View logs for code generation
|
||||
|
||||
### Trades Not Accepting
|
||||
|
||||
**Symptoms:**
|
||||
- User accepts trade in Steam
|
||||
- Balance not credited
|
||||
- Trade stuck in pending
|
||||
|
||||
**Solutions:**
|
||||
1. Check bot event handlers are working
|
||||
2. Verify bot polling is active
|
||||
3. Check trade state in database
|
||||
4. Manually check trade status in Steam
|
||||
5. Review bot logs for errors
|
||||
|
||||
---
|
||||
|
||||
## 📈 Performance Optimization
|
||||
|
||||
### 1. Optimal Bot Count
|
||||
|
||||
**Small Sites** (<100 trades/day):
|
||||
- 2-3 bots sufficient
|
||||
- No proxies needed initially
|
||||
|
||||
**Medium Sites** (100-500 trades/day):
|
||||
- 3-5 bots recommended
|
||||
- 1 proxy per bot
|
||||
|
||||
**Large Sites** (>500 trades/day):
|
||||
- 5-10 bots
|
||||
- Multiple proxies per region
|
||||
- Redis queue for trade management
|
||||
|
||||
### 2. Proxy Pool Management
|
||||
|
||||
```javascript
|
||||
// Rotate proxies periodically
|
||||
setInterval(() => {
|
||||
console.log('🔄 Checking proxy health...');
|
||||
const health = botManager.getAllBotsHealth();
|
||||
|
||||
health.forEach(bot => {
|
||||
if (bot.errorCount > 20) {
|
||||
console.warn(`⚠️ ${bot.botId} has high error count, consider rotating proxy`);
|
||||
}
|
||||
});
|
||||
}, 60 * 60 * 1000); // Check every hour
|
||||
```
|
||||
|
||||
### 3. Trade Queue System
|
||||
|
||||
For high volume, implement queue:
|
||||
|
||||
```javascript
|
||||
import Bull from 'bull';
|
||||
|
||||
const tradeQueue = new Bull('steam-trades', {
|
||||
redis: { host: 'localhost', port: 6379 }
|
||||
});
|
||||
|
||||
tradeQueue.process(5, async (job) => { // Process 5 at a time
|
||||
const { userId, items, tradeUrl } = job.data;
|
||||
return await botManager.createTradeOffer({
|
||||
tradeUrl,
|
||||
itemsToReceive: items,
|
||||
userId
|
||||
});
|
||||
});
|
||||
|
||||
// Add to queue
|
||||
await tradeQueue.add({ userId, items, tradeUrl }, {
|
||||
attempts: 3,
|
||||
backoff: { type: 'exponential', delay: 5000 }
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Production Checklist
|
||||
|
||||
Before going live:
|
||||
|
||||
- [ ] All bot accounts created and funded
|
||||
- [ ] Steam Mobile Authenticator enabled on all bots
|
||||
- [ ] Shared/identity secrets extracted
|
||||
- [ ] Proxies tested and working
|
||||
- [ ] Configuration file created
|
||||
- [ ] All bots successfully login
|
||||
- [ ] Test trade offer sent and accepted
|
||||
- [ ] Verification codes displayed correctly
|
||||
- [ ] Balance credits after acceptance
|
||||
- [ ] Trade events firing properly
|
||||
- [ ] Error handling tested
|
||||
- [ ] Monitoring dashboard set up
|
||||
- [ ] Rate limiting implemented
|
||||
- [ ] Backup bots configured
|
||||
- [ ] Documentation updated
|
||||
- [ ] Team trained on bot management
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Example: 3-Bot Setup
|
||||
|
||||
### Complete Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"bots": [
|
||||
{
|
||||
"accountName": "turbotrades_bot1",
|
||||
"password": "StrongPass123!@#",
|
||||
"sharedSecret": "Xj9mK3pL2qN5vB8cD4fG7hJ1kM6nP0rT",
|
||||
"identitySecret": "Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY_HERE",
|
||||
"proxy": {
|
||||
"type": "socks5",
|
||||
"host": "us-proxy1.example.com",
|
||||
"port": 1080,
|
||||
"username": "proxyuser1",
|
||||
"password": "ProxyPass123"
|
||||
},
|
||||
"maxConcurrentTrades": 15,
|
||||
"pollInterval": 25000,
|
||||
"tradeTimeout": 600000
|
||||
},
|
||||
{
|
||||
"accountName": "turbotrades_bot2",
|
||||
"password": "AnotherStrong456!@#",
|
||||
"sharedSecret": "Yh8jM2kL4pN7vC9dF3gH6jK0mP5qR1tS",
|
||||
"identitySecret": "Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk1Ll",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY_HERE",
|
||||
"proxy": {
|
||||
"type": "socks5",
|
||||
"host": "eu-proxy1.example.com",
|
||||
"port": 1080,
|
||||
"username": "proxyuser2",
|
||||
"password": "ProxyPass456"
|
||||
},
|
||||
"maxConcurrentTrades": 15,
|
||||
"pollInterval": 25000,
|
||||
"tradeTimeout": 600000
|
||||
},
|
||||
{
|
||||
"accountName": "turbotrades_bot3",
|
||||
"password": "SecureBot789!@#",
|
||||
"sharedSecret": "Zi7kN1mL3oP6wD8eG2hJ5lM9qT4rU0vX",
|
||||
"identitySecret": "Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk1Ll2Mm",
|
||||
"steamApiKey": "YOUR_STEAM_API_KEY_HERE",
|
||||
"proxy": {
|
||||
"type": "http",
|
||||
"host": "asia-proxy1.example.com",
|
||||
"port": 8080,
|
||||
"username": "proxyuser3",
|
||||
"password": "ProxyPass789"
|
||||
},
|
||||
"maxConcurrentTrades": 15,
|
||||
"pollInterval": 25000,
|
||||
"tradeTimeout": 600000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Startup Script
|
||||
|
||||
```javascript
|
||||
import { getSteamBotManager } from './services/steamBot.js';
|
||||
import fs from 'fs';
|
||||
|
||||
async function startBots() {
|
||||
console.log('🤖 Starting TurboTrades Bot System...\n');
|
||||
|
||||
// Load configuration
|
||||
const config = JSON.parse(
|
||||
fs.readFileSync('./config/steam-bots.json', 'utf8')
|
||||
);
|
||||
|
||||
// Initialize bot manager
|
||||
const botManager = getSteamBotManager();
|
||||
|
||||
// Start all bots
|
||||
const results = await botManager.initialize(config.bots);
|
||||
|
||||
// Show results
|
||||
results.forEach(result => {
|
||||
if (result.success) {
|
||||
console.log(`✅ ${result.botId} - Ready`);
|
||||
} else {
|
||||
console.log(`❌ ${result.botId} - Failed: ${result.error}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n📊 System Status:');
|
||||
console.log(botManager.getStats());
|
||||
|
||||
return botManager;
|
||||
}
|
||||
|
||||
// Start bots
|
||||
const botManager = await startBots();
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n👋 Shutting down bots...');
|
||||
botManager.shutdown();
|
||||
process.exit(0);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- **Steam Web API**: https://developer.valvesoftware.com/wiki/Steam_Web_API
|
||||
- **node-steam-user**: https://github.com/DoctorMcKay/node-steam-user
|
||||
- **steam-tradeoffer-manager**: https://github.com/DoctorMcKay/node-steam-tradeoffer-manager
|
||||
- **SOCKS Proxy Agent**: https://www.npmjs.com/package/socks-proxy-agent
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Summary
|
||||
|
||||
You now have:
|
||||
- ✅ Multiple Steam bots with load balancing
|
||||
- ✅ Proxy support for each bot
|
||||
- ✅ Verification codes for security
|
||||
- ✅ Automatic failover
|
||||
- ✅ Health monitoring
|
||||
- ✅ Event-driven architecture
|
||||
- ✅ Production-ready setup
|
||||
|
||||
**Next Steps:**
|
||||
1. Set up bot accounts
|
||||
2. Configure proxies
|
||||
3. Create configuration file
|
||||
4. Test bot login
|
||||
5. Create test trade with verification code
|
||||
6. Integrate with sell endpoint
|
||||
7. Add UI for verification code display
|
||||
8. Deploy to production
|
||||
|
||||
**The system will now:**
|
||||
- Accept sell requests from users
|
||||
- Generate unique verification code
|
||||
- Select best available bot
|
||||
- Create trade offer with code in message
|
||||
- Wait for user to accept
|
||||
- Credit balance ONLY after trade accepted
|
||||
- Handle failures gracefully
|
||||
|
||||
🚀 **Your marketplace is now secure and scalable!**
|
||||
Reference in New Issue
Block a user