diff --git a/docs/API.md b/docs/API.md index 2d6d031..1a6fd20 100644 --- a/docs/API.md +++ b/docs/API.md @@ -68,6 +68,7 @@ curl -H "Authorization: Bearer your_api_token_here" http://localhost:8888/endpoi ## Table of Contents - [Authentication](#-authentication) - [Health & Info](#health--info) +- [Public Download Endpoint](#public-download-endpoint) - [Download Endpoints](#download-endpoints) - [Transcription Endpoints](#transcription-endpoints) - [Conversion Endpoints](#conversion-endpoints) @@ -84,6 +85,8 @@ curl -H "Authorization: Bearer your_api_token_here" http://localhost:8888/endpoi ### GET /health Health check endpoint. +**Authentication**: Not required (public) + **Response:** ```json { @@ -95,6 +98,8 @@ Health check endpoint. ### GET /api Get API information and available endpoints. +**Authentication**: Not required (public) + **Response:** ```json { @@ -104,6 +109,67 @@ Get API information and available endpoints. } ``` +--- + +## Public Download Endpoint + +### GET /public/download/:filename +Public endpoint to download files without authentication. + +**Authentication**: Not required (public) + +**Purpose**: Share direct download links for generated files (MP3, transcriptions, translations, summaries) without requiring API authentication. + +**URL Parameters:** +- `filename` (required): Name of the file to download + +**Security**: +- Directory traversal protection enabled (uses `path.basename()`) +- Only files in the configured OUTPUT_DIR are accessible +- No authentication required + +**Example:** +```bash +# Direct download (no auth needed) +curl -O http://localhost:8888/public/download/my_video.mp3 + +# Or simply open in browser +http://localhost:8888/public/download/my_video.mp3 +``` + +**Response (Success):** +- File download with proper Content-Disposition headers +- Browser will prompt to download the file + +**Response (Error - 404):** +```json +{ + "error": "File not found", + "message": "File 'my_video.mp3' does not exist" +} +``` + +**Response (Error - 500):** +```json +{ + "error": "Download failed", + "message": "Error details..." +} +``` + +**Use Cases:** +- Share download links via email/chat +- Embed in web applications +- Direct browser downloads +- Public file sharing + +**Note**: After processing (download, transcription, etc.), use the returned `filePath` or `fileUrl` from authenticated endpoints, then construct public URL: +``` +/public/download/{basename_of_filePath} +``` + +--- + ### GET /info Get information about a YouTube video or playlist. diff --git a/extract-and-upload-cookies.sh b/extract-and-upload-cookies.sh index ae7da47..ada680f 100755 --- a/extract-and-upload-cookies.sh +++ b/extract-and-upload-cookies.sh @@ -1,135 +1,135 @@ -#!/bin/bash -# Extract and Upload Cookies - All-in-one script -# This script extracts YouTube cookies from your browser and uploads them to the API - -set -e # Exit on error - -# Colors for pretty output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Configuration -API_URL="${API_URL:-http://localhost:8888}" -API_TOKEN="${API_TOKEN:-}" -TEMP_COOKIES="/tmp/youtube-cookies-temp.txt" - -echo -e "${BLUE}========================================${NC}" -echo -e "${BLUE}YouTube Cookies Extractor & Uploader${NC}" -echo -e "${BLUE}========================================${NC}" -echo "" - -# Step 1: Check if API token is set -if [ -z "$API_TOKEN" ]; then - echo -e "${YELLOW}âš ī¸ API_TOKEN not set in environment${NC}" - echo -e "Please enter your API token:" - read -s API_TOKEN - echo "" -fi - -# Step 2: Detect available browsers -echo -e "${BLUE}🔍 Detecting browsers...${NC}" -AVAILABLE_BROWSERS=() - -if command -v google-chrome &> /dev/null || command -v chromium &> /dev/null || [ -d "$HOME/.config/google-chrome" ] || [ -d "$HOME/.config/chromium" ]; then - AVAILABLE_BROWSERS+=("chrome") -fi - -if command -v firefox &> /dev/null || [ -d "$HOME/.mozilla/firefox" ]; then - AVAILABLE_BROWSERS+=("firefox") -fi - -if command -v microsoft-edge &> /dev/null || [ -d "$HOME/.config/microsoft-edge" ]; then - AVAILABLE_BROWSERS+=("edge") -fi - -if [ ${#AVAILABLE_BROWSERS[@]} -eq 0 ]; then - echo -e "${RED}❌ No supported browsers found${NC}" - echo -e "${YELLOW}Supported browsers: Chrome, Firefox, Edge${NC}" - echo "" - echo -e "${YELLOW}Alternative: Manually export cookies${NC}" - echo -e "1. Install browser extension 'Get cookies.txt LOCALLY'" - echo -e "2. Visit youtube.com and login" - echo -e "3. Export cookies to a file" - echo -e "4. Run: curl -X POST -H \"X-API-Key: \$API_TOKEN\" -F \"cookies=@youtube-cookies.txt\" $API_URL/admin/upload-cookies" - exit 1 -fi - -echo -e "${GREEN}✓ Found browsers:${NC} ${AVAILABLE_BROWSERS[*]}" -echo "" - -# Step 3: Let user choose browser -if [ ${#AVAILABLE_BROWSERS[@]} -eq 1 ]; then - BROWSER="${AVAILABLE_BROWSERS[0]}" - echo -e "${GREEN}Using browser: $BROWSER${NC}" -else - echo -e "${YELLOW}Multiple browsers found. Choose one:${NC}" - select BROWSER in "${AVAILABLE_BROWSERS[@]}"; do - if [ -n "$BROWSER" ]; then - break - fi - done -fi - -echo "" - -# Step 4: Check if yt-dlp is installed -if ! command -v yt-dlp &> /dev/null; then - echo -e "${RED}❌ yt-dlp is not installed${NC}" - echo -e "${YELLOW}Install with: pip install yt-dlp${NC}" - echo -e "${YELLOW}Or: sudo apt install yt-dlp${NC}" - exit 1 -fi - -# Step 5: Extract cookies using yt-dlp -echo -e "${BLUE}đŸĒ Extracting cookies from $BROWSER...${NC}" - -if yt-dlp --cookies-from-browser "$BROWSER" --cookies "$TEMP_COOKIES" --no-download "https://www.youtube.com" > /dev/null 2>&1; then - echo -e "${GREEN}✓ Cookies extracted successfully${NC}" -else - echo -e "${RED}❌ Failed to extract cookies${NC}" - echo -e "${YELLOW}Make sure:${NC}" - echo -e " 1. You're logged into YouTube in $BROWSER" - echo -e " 2. $BROWSER is closed (some browsers lock the cookies database)" - echo -e " 3. You have the necessary permissions" - exit 1 -fi - -# Step 6: Upload cookies to API -echo -e "${BLUE}📤 Uploading cookies to API...${NC}" - -UPLOAD_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ - -H "X-API-Key: $API_TOKEN" \ - -F "cookies=@$TEMP_COOKIES" \ - "$API_URL/admin/upload-cookies") - -HTTP_CODE=$(echo "$UPLOAD_RESPONSE" | tail -n1) -RESPONSE_BODY=$(echo "$UPLOAD_RESPONSE" | head -n-1) - -if [ "$HTTP_CODE" = "200" ]; then - echo -e "${GREEN}✓ Cookies uploaded successfully!${NC}" - echo "" - echo -e "${GREEN}═══════════════════════════════════════${NC}" - echo -e "${GREEN}SUCCESS! You're all set!${NC}" - echo -e "${GREEN}═══════════════════════════════════════${NC}" - echo "" - echo "$RESPONSE_BODY" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE_BODY" - echo "" - echo -e "${BLUE}â„šī¸ Your cookies are now active${NC}" - echo -e "${BLUE}â„šī¸ YouTube downloads should work without bot detection${NC}" - echo -e "${BLUE}â„šī¸ Cookies expire after a few weeks - run this script again if needed${NC}" -else - echo -e "${RED}❌ Failed to upload cookies${NC}" - echo -e "${RED}HTTP Status: $HTTP_CODE${NC}" - echo "" - echo "$RESPONSE_BODY" - exit 1 -fi - -# Step 7: Cleanup -rm -f "$TEMP_COOKIES" - -echo "" -echo -e "${GREEN}🎉 All done!${NC}" +#!/bin/bash +# Extract and Upload Cookies - All-in-one script +# This script extracts YouTube cookies from your browser and uploads them to the API + +set -e # Exit on error + +# Colors for pretty output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +API_URL="${API_URL:-http://localhost:8888}" +API_TOKEN="${API_TOKEN:-}" +TEMP_COOKIES="/tmp/youtube-cookies-temp.txt" + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}YouTube Cookies Extractor & Uploader${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# Step 1: Check if API token is set +if [ -z "$API_TOKEN" ]; then + echo -e "${YELLOW}âš ī¸ API_TOKEN not set in environment${NC}" + echo -e "Please enter your API token:" + read -s API_TOKEN + echo "" +fi + +# Step 2: Detect available browsers +echo -e "${BLUE}🔍 Detecting browsers...${NC}" +AVAILABLE_BROWSERS=() + +if command -v google-chrome &> /dev/null || command -v chromium &> /dev/null || [ -d "$HOME/.config/google-chrome" ] || [ -d "$HOME/.config/chromium" ]; then + AVAILABLE_BROWSERS+=("chrome") +fi + +if command -v firefox &> /dev/null || [ -d "$HOME/.mozilla/firefox" ]; then + AVAILABLE_BROWSERS+=("firefox") +fi + +if command -v microsoft-edge &> /dev/null || [ -d "$HOME/.config/microsoft-edge" ]; then + AVAILABLE_BROWSERS+=("edge") +fi + +if [ ${#AVAILABLE_BROWSERS[@]} -eq 0 ]; then + echo -e "${RED}❌ No supported browsers found${NC}" + echo -e "${YELLOW}Supported browsers: Chrome, Firefox, Edge${NC}" + echo "" + echo -e "${YELLOW}Alternative: Manually export cookies${NC}" + echo -e "1. Install browser extension 'Get cookies.txt LOCALLY'" + echo -e "2. Visit youtube.com and login" + echo -e "3. Export cookies to a file" + echo -e "4. Run: curl -X POST -H \"X-API-Key: \$API_TOKEN\" -F \"cookies=@youtube-cookies.txt\" $API_URL/admin/upload-cookies" + exit 1 +fi + +echo -e "${GREEN}✓ Found browsers:${NC} ${AVAILABLE_BROWSERS[*]}" +echo "" + +# Step 3: Let user choose browser +if [ ${#AVAILABLE_BROWSERS[@]} -eq 1 ]; then + BROWSER="${AVAILABLE_BROWSERS[0]}" + echo -e "${GREEN}Using browser: $BROWSER${NC}" +else + echo -e "${YELLOW}Multiple browsers found. Choose one:${NC}" + select BROWSER in "${AVAILABLE_BROWSERS[@]}"; do + if [ -n "$BROWSER" ]; then + break + fi + done +fi + +echo "" + +# Step 4: Check if yt-dlp is installed +if ! command -v yt-dlp &> /dev/null; then + echo -e "${RED}❌ yt-dlp is not installed${NC}" + echo -e "${YELLOW}Install with: pip install yt-dlp${NC}" + echo -e "${YELLOW}Or: sudo apt install yt-dlp${NC}" + exit 1 +fi + +# Step 5: Extract cookies using yt-dlp +echo -e "${BLUE}đŸĒ Extracting cookies from $BROWSER...${NC}" + +if yt-dlp --cookies-from-browser "$BROWSER" --cookies "$TEMP_COOKIES" --no-download "https://www.youtube.com" > /dev/null 2>&1; then + echo -e "${GREEN}✓ Cookies extracted successfully${NC}" +else + echo -e "${RED}❌ Failed to extract cookies${NC}" + echo -e "${YELLOW}Make sure:${NC}" + echo -e " 1. You're logged into YouTube in $BROWSER" + echo -e " 2. $BROWSER is closed (some browsers lock the cookies database)" + echo -e " 3. You have the necessary permissions" + exit 1 +fi + +# Step 6: Upload cookies to API +echo -e "${BLUE}📤 Uploading cookies to API...${NC}" + +UPLOAD_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ + -H "X-API-Key: $API_TOKEN" \ + -F "cookies=@$TEMP_COOKIES" \ + "$API_URL/admin/upload-cookies") + +HTTP_CODE=$(echo "$UPLOAD_RESPONSE" | tail -n1) +RESPONSE_BODY=$(echo "$UPLOAD_RESPONSE" | head -n-1) + +if [ "$HTTP_CODE" = "200" ]; then + echo -e "${GREEN}✓ Cookies uploaded successfully!${NC}" + echo "" + echo -e "${GREEN}═══════════════════════════════════════${NC}" + echo -e "${GREEN}SUCCESS! You're all set!${NC}" + echo -e "${GREEN}═══════════════════════════════════════${NC}" + echo "" + echo "$RESPONSE_BODY" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE_BODY" + echo "" + echo -e "${BLUE}â„šī¸ Your cookies are now active${NC}" + echo -e "${BLUE}â„šī¸ YouTube downloads should work without bot detection${NC}" + echo -e "${BLUE}â„šī¸ Cookies expire after a few weeks - run this script again if needed${NC}" +else + echo -e "${RED}❌ Failed to upload cookies${NC}" + echo -e "${RED}HTTP Status: $HTTP_CODE${NC}" + echo "" + echo "$RESPONSE_BODY" + exit 1 +fi + +# Step 7: Cleanup +rm -f "$TEMP_COOKIES" + +echo "" +echo -e "${GREEN}🎉 All done!${NC}" diff --git a/refresh-cookies.sh b/refresh-cookies.sh new file mode 100755 index 0000000..1d3a637 --- /dev/null +++ b/refresh-cookies.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Auto-refresh cookies from /tmp/share if they exist and are newer + +SHARE_COOKIES="/tmp/share/youtube-cookies.txt" +LOCAL_COOKIES="/home/debian/videotomp3transcriptor/youtube-cookies.txt" + +if [ -f "$SHARE_COOKIES" ]; then + # Copy if share is newer or local doesn't exist + if [ ! -f "$LOCAL_COOKIES" ] || [ "$SHARE_COOKIES" -nt "$LOCAL_COOKIES" ]; then + cp "$SHARE_COOKIES" "$LOCAL_COOKIES" + chmod 600 "$LOCAL_COOKIES" + echo "[$(date)] ✓ Cookies refreshed from /tmp/share" + fi +fi diff --git a/src/server.js b/src/server.js index 879e614..557dd14 100644 --- a/src/server.js +++ b/src/server.js @@ -102,7 +102,8 @@ app.use((req, res, next) => { const authenticate = (req, res, next) => { // Skip authentication for public endpoints const publicEndpoints = ['/health', '/api']; - if (publicEndpoints.includes(req.path)) { + // Allow public download endpoint + if (publicEndpoints.includes(req.path) || req.path.startsWith('/public/download/')) { return next(); } @@ -173,6 +174,47 @@ app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); +/** + * GET /public/download/:filename + * Public endpoint to download files without authentication + */ +app.get('/public/download/:filename', (req, res) => { + try { + const { filename } = req.params; + + // Security: prevent directory traversal + const safeName = path.basename(filename); + const filePath = path.join(OUTPUT_DIR, safeName); + + // Check if file exists + if (!fs.existsSync(filePath)) { + return res.status(404).json({ + error: 'File not found', + message: `File '${safeName}' does not exist` + }); + } + + // Send file with proper headers + res.download(filePath, safeName, (err) => { + if (err) { + console.error(`[Public Download] Error: ${err.message}`); + if (!res.headersSent) { + res.status(500).json({ + error: 'Download failed', + message: err.message + }); + } + } + }); + } catch (error) { + console.error(`[Public Download] Error: ${error.message}`); + res.status(500).json({ + error: 'Server error', + message: error.message + }); + } +}); + /** * GET /info?url= * Get info about a video or playlist @@ -1429,6 +1471,7 @@ app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); console.log('\nEndpoints:'); console.log(' GET /health - Health check'); + console.log(' GET /public/download/:filename - Public file download (no auth)'); console.log(' GET /info?url= - Get video/playlist info'); console.log(' POST /download - Download as MP3'); console.log(' POST /transcribe - Transcribe audio file');