feat: Add VPS storage system and complete integration

🎯 Overview:
Implemented complete VPS-based storage system allowing the iOS app to download
and store manga chapters on the VPS for ad-free offline reading.

📦 Backend Changes:
- Added storage.js service for managing chapter downloads (270 lines)
- Updated server.js with 6 new storage endpoints:
  - POST /api/download - Download chapters to VPS
  - GET /api/storage/chapters/:mangaSlug - List downloaded chapters
  - GET /api/storage/chapter/:mangaSlug/:chapterNumber - Check download status
  - GET /api/storage/image/:mangaSlug/:chapterNumber/:pageIndex - Serve images
  - DELETE /api/storage/chapter/:mangaSlug/:chapterNumber - Delete chapters
  - GET /api/storage/stats - Get storage statistics
- Fixed scraper.js Puppeteer compatibility issues (waitForTimeout, networkidle0)
- Added comprehensive test suite:
  - test-vps-flow.js (13 tests - 100% pass rate)
  - test-concurrent-downloads.js (10 tests for parallel operations)
  - run-tests.sh automation script

📱 iOS App Changes:
- Created APIConfig.swift with VPS connection settings
- Created VPSAPIClient.swift service (727 lines) for backend communication
- Updated MangaDetailView.swift with VPS download integration:
  - Cloud icon for VPS-available chapters
  - Upload button to download chapters to VPS
  - Progress indicators for active downloads
  - Bulk download options (last 10 or all chapters)
- Updated ReaderView.swift to load images from VPS first
- Progressive enhancement: app works without VPS, enhances when available

 Tests:
- All 13 VPS flow tests passing (100%)
- Tests verify: scraping, downloading, storage, serving, deletion, stats
- Chapter 789 download test: 21 images, 4.68 MB
- Concurrent download tests verify no race conditions

🔧 Configuration:
- VPS URL: https://gitea.cbcren.online:3001
- Storage location: /home/ren/ios/MangaReader/storage/
- Static file serving: /storage path

📚 Documentation:
- Added VPS_INTEGRATION_SUMMARY.md - Complete feature overview
- Added CHANGES.md - Detailed code changes reference
- Added TEST_README.md, TEST_QUICK_START.md, TEST_SUMMARY.md
- Added APIConfig README with usage examples

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-02-04 16:20:28 +01:00
parent b474182dd9
commit 83e25e3bd6
18 changed files with 5449 additions and 32 deletions

299
backend/run-tests.sh Executable file
View File

@@ -0,0 +1,299 @@
#!/bin/bash
# MangaReader Backend Integration Test Runner
# This script helps you run the integration tests easily
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
BACKEND_DIR="/home/ren/ios/MangaReader/backend"
SERVER_PID_FILE="$BACKEND_DIR/.server.pid"
LOG_DIR="$BACKEND_DIR/logs"
# Functions
log_info() {
echo -e "${BLUE} ${1}${NC}"
}
log_success() {
echo -e "${GREEN}${1}${NC}"
}
log_error() {
echo -e "${RED}${1}${NC}"
}
log_warning() {
echo -e "${YELLOW}${1}${NC}"
}
print_header() {
echo ""
echo "============================================================"
echo " $1"
echo "============================================================"
echo ""
}
# Create logs directory if it doesn't exist
mkdir -p "$LOG_DIR"
# Check if server is running
is_server_running() {
if [ -f "$SERVER_PID_FILE" ]; then
PID=$(cat "$SERVER_PID_FILE")
if ps -p $PID > /dev/null 2>&1; then
return 0
else
rm -f "$SERVER_PID_FILE"
return 1
fi
fi
return 1
}
# Start server
start_server() {
print_header "Starting Server"
if is_server_running; then
log_warning "Server is already running (PID: $(cat $SERVER_PID_FILE))"
return 0
fi
log_info "Starting server in background..."
cd "$BACKEND_DIR"
# Start server and capture PID
nohup node server.js > "$LOG_DIR/server.log" 2>&1 &
SERVER_PID=$!
echo $SERVER_PID > "$SERVER_PID_FILE"
# Wait for server to start
log_info "Waiting for server to start..."
sleep 3
# Check if server started successfully
if is_server_running; then
log_success "Server started successfully (PID: $SERVER_PID)"
log_info "Logs: $LOG_DIR/server.log"
# Verify server is responding
if curl -s http://localhost:3000/api/health > /dev/null; then
log_success "Server is responding to requests"
else
log_warning "Server started but not responding yet (may need more time)"
fi
else
log_error "Failed to start server"
log_info "Check logs: $LOG_DIR/server.log"
exit 1
fi
}
# Stop server
stop_server() {
print_header "Stopping Server"
if ! is_server_running; then
log_warning "Server is not running"
return 0
fi
PID=$(cat "$SERVER_PID_FILE")
log_info "Stopping server (PID: $PID)..."
kill $PID 2>/dev/null || true
sleep 2
# Force kill if still running
if ps -p $PID > /dev/null 2>&1; then
log_warning "Force killing server..."
kill -9 $PID 2>/dev/null || true
fi
rm -f "$SERVER_PID_FILE"
log_success "Server stopped"
}
# Show server logs
show_logs() {
if [ -f "$LOG_DIR/server.log" ]; then
tail -f "$LOG_DIR/server.log"
else
log_error "No log file found"
fi
}
# Run VPS flow test
run_vps_flow_test() {
print_header "Running VPS Flow Test"
if ! is_server_running; then
log_error "Server is not running. Start it with: $0 start"
exit 1
fi
cd "$BACKEND_DIR"
log_info "Executing test-vps-flow.js..."
echo ""
node test-vps-flow.js
if [ $? -eq 0 ]; then
log_success "VPS Flow Test PASSED"
return 0
else
log_error "VPS Flow Test FAILED"
return 1
fi
}
# Run concurrent downloads test
run_concurrent_test() {
print_header "Running Concurrent Downloads Test"
if ! is_server_running; then
log_error "Server is not running. Start it with: $0 start"
exit 1
fi
cd "$BACKEND_DIR"
log_info "Executing test-concurrent-downloads.js..."
echo ""
node test-concurrent-downloads.js
if [ $? -eq 0 ]; then
log_success "Concurrent Downloads Test PASSED"
return 0
else
log_error "Concurrent Downloads Test FAILED"
return 1
fi
}
# Run all tests
run_all_tests() {
print_header "Running All Integration Tests"
local failed=0
run_vps_flow_test || failed=1
echo ""
run_concurrent_test || failed=1
echo ""
print_header "Test Summary"
if [ $failed -eq 0 ]; then
log_success "ALL TESTS PASSED"
return 0
else
log_error "SOME TESTS FAILED"
return 1
fi
}
# Cleanup test data
cleanup() {
print_header "Cleaning Up Test Data"
log_info "Removing test chapters from storage..."
STORAGE_DIR="/home/ren/ios/MangaReader/storage/manga/one-piece_1695365223767"
if [ -d "$STORAGE_DIR" ]; then
rm -rf "$STORAGE_DIR"
log_success "Test data removed"
else
log_info "No test data found"
fi
}
# Show help
show_help() {
cat << EOF
MangaReader Backend Integration Test Runner
Usage: $0 [COMMAND]
Commands:
start Start the server in background
stop Stop the server
restart Restart the server
logs Show server logs (tail -f)
status Check server status
vps-flow Run VPS flow integration test
concurrent Run concurrent downloads test
all Run all tests
cleanup Clean up test data
help Show this help message
Examples:
$0 start # Start server
$0 vps-flow # Run VPS flow test
$0 all # Run all tests
$0 cleanup # Clean up test data
$0 stop # Stop server
For full testing workflow:
$0 start && $0 all && $0 cleanup && $0 stop
EOF
}
# Main
case "${1:-}" in
start)
start_server
;;
stop)
stop_server
;;
restart)
stop_server
sleep 1
start_server
;;
logs)
show_logs
;;
status)
if is_server_running; then
log_success "Server is running (PID: $(cat $SERVER_PID_FILE))"
exit 0
else
log_error "Server is not running"
exit 1
fi
;;
vps-flow)
run_vps_flow_test
;;
concurrent)
run_concurrent_test
;;
all)
run_all_tests
;;
cleanup)
cleanup
;;
help|--help|-h)
show_help
;;
*)
log_error "Unknown command: ${1:-}"
echo ""
show_help
exit 1
;;
esac