ydisk-downloader 1.0.0
Fast and efficient Yandex Disk folder downloader with async support
License: MIT
Requires Python: >=3.9
Keywords: yandex, disk, downloader, async, cloud

# YDisk Downloader

Fast and efficient Yandex Disk folder downloader with async support.

A Python command-line tool for downloading folders from Yandex Disk with support for:
- 📁 **Public links** - No authentication required
- 🔐 **Private folders** - OAuth token authentication
- ⚡ **Concurrent downloads** - Multiple files at once for speed
- 📊 **Progress tracking** - Visual progress bar with tqdm
- 🔄 **Resume capability** - Skip already downloaded files
- 📂 **Folder structure** - Preserves directory hierarchy

## Installation

### From Source

```bash
# Clone the repository
git clone https://github.com/MyDum-bsu/YDiskDownloader.git
cd YDiskDownloader

# Install with pip
pip install -e .

# Or install with development dependencies
pip install -e ".[dev]"
```

### Using pip (after publishing)

```bash
pip install ydisk-downloader
```

## Quick Start

### Download from Public Link

```bash
# Basic usage
ydisk-downloader download https://disk.yandex.ru/d/xxxxx /path/to/save

# Example: Download to external HDD
ydisk-downloader download https://disk.yandex.ru/d/abc123xyz /media/external/backup
```

### Download Private Folder

```bash
# With token option
ydisk-downloader download /Photos/Vacation /path/to/save --token YOUR_TOKEN

# With environment variable
export YANDEX_DISK_TOKEN=your_token_here
ydisk-downloader download /Photos/Vacation /path/to/save
```

## Getting an OAuth Token

To access private folders, you need an OAuth token:

1. Visit the authorization URL:
   ```
   https://oauth.yandex.com/authorize?response_type=token&client_id=c0ebe342af7d48fbbbfcf2d2eedb8f9b
   ```

2. Log in to your Yandex account

3. Grant permission to the application

4. Copy the token from the redirect URL (after `#access_token=`)

Or use the built-in help:
```bash
ydisk-downloader token-help
```

### Token Storage Options

You can store your token in several ways:

1. **Environment variable** (recommended for scripts):
   ```bash
   export YANDEX_DISK_TOKEN=your_token_here
   ```

2. **Command-line option**:
   ```bash
   ydisk-downloader download SOURCE DEST --token YOUR_TOKEN
   ```

3. **Configuration file**:
   ```bash
   # Save token to file
   echo "your_token_here" > ~/.ydisk-token
   ```

## Usage

### Commands

```bash
# Download a folder
ydisk-downloader download SOURCE DESTINATION [OPTIONS]

# Show disk information
ydisk-downloader info --token YOUR_TOKEN

# Get help with tokens
ydisk-downloader token-help

# Show version
ydisk-downloader --version
```

### Download Options

| Option | Description |
|--------|-------------|
| `--token, -t` | OAuth token for private folders |
| `--concurrent, -c` | Maximum concurrent downloads (default: 5) |
| `--no-skip` | Download files even if they already exist |
| `--no-verify` | Skip file size verification after download |
| `--quiet, -q` | Suppress progress output |
| `--no-banner` | Don't show the startup banner |

### Examples

```bash
# Download with 10 concurrent connections
ydisk-downloader download https://disk.yandex.ru/d/xxxxx /path/to/save -c 10

# Re-download all files (don't skip existing)
ydisk-downloader download https://disk.yandex.ru/d/xxxxx /path/to/save --no-skip

# Quiet mode (no progress bar)
ydisk-downloader download https://disk.yandex.ru/d/xxxxx /path/to/save -q

# Download private folder
ydisk-downloader download /Documents/Work /backup/work --token $YANDEX_DISK_TOKEN
```

## Python API

You can also use the library programmatically:

```python
import asyncio
from ydisk_downloader import YDiskDownloader, print_stats

async def main():
    # Create downloader
    async with YDiskDownloader(
        max_concurrent=10,
        skip_existing=True,
        verify_size=True,
    ) as downloader:
        # Download from public link
        stats = await downloader.download_folder(
            "https://disk.yandex.ru/d/xxxxx",
            "/path/to/save"
        )
        
        # Print statistics
        print_stats(stats)
        
        print(f"Downloaded: {stats.downloaded_files} files")
        print(f"Total size: {stats.downloaded_size} bytes")
        print(f"Skipped: {stats.skipped_files} files")
        print(f"Failed: {stats.failed_files} files")

asyncio.run(main())
```

### Using with Private Folders

```python
import asyncio
from ydisk_downloader import YDiskDownloader

async def main():
    async with YDiskDownloader(token="your_token_here") as downloader:
        stats = await downloader.download_folder(
            "/Photos/Vacation",
            "/backup/vacation"
        )

asyncio.run(main())
```

### Advanced Usage

```python
import asyncio
from ydisk_downloader import YDiskDownloader, YandexDiskClient

async def list_files():
    """List all files in a private folder."""
    async with YandexDiskClient(token="your_token") as client:
        files = await client.collect_all_files("/Photos")
        for f in files:
            print(f"{f.name} - {f.size} bytes")

asyncio.run(list_files())
```

## Features

### Concurrent Downloads

The downloader uses asyncio and aiohttp to download multiple files concurrently, significantly improving download speed for folders with many small files.

### Resume Capability

By default, the downloader skips files that already exist in the destination with the correct size. This allows you to resume interrupted downloads without re-downloading everything.

### Progress Tracking

A progress bar shows:
- Total bytes downloaded
- Download speed
- Estimated time remaining

### Error Handling

The downloader handles various error conditions:
- Network errors with automatic retries
- Rate limiting with exponential backoff
- Authentication errors
- File system errors

## Requirements

- Python 3.9 or higher
- Linux, macOS, or Windows

## Dependencies

- `aiohttp` - Async HTTP client
- `aiofiles` - Async file operations
- `tqdm` - Progress bars
- `click` - CLI framework

## Troubleshooting

### "OAuth token required" error

Make sure you've provided a valid OAuth token:
```bash
export YANDEX_DISK_TOKEN=your_token
# or
ydisk-downloader download SOURCE DEST --token your_token
```

### "Resource not found" error

- For public links: Make sure the link is correct and the resource is still public
- For private folders: Make sure the path is correct and you have access

### Slow downloads

Try increasing the number of concurrent downloads:
```bash
ydisk-downloader download SOURCE DEST -c 10
```

### "No write permission" error

Make sure you have write access to the destination directory:
```bash
# Check permissions
ls -la /path/to/destination

# Create directory if needed
mkdir -p /path/to/destination
```

## License

MIT License - see LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## Acknowledgments

- [Yandex Disk REST API](https://yandex.com/dev/disk-api/doc/en/)
- [aiohttp](https://docs.aiohttp.org/)
- [tqdm](https://github.com/tqdm/tqdm)