# TorrentEngine Library
Мощная библиотека для Android, обеспечивающая полноценную работу с торрентами через LibTorrent4j.
## 🎯 Возможности
- ✅ **Загрузка из magnet-ссылок** - получение метаданных и загрузка файлов
- ✅ **Выбор файлов** - возможность выбирать какие файлы загружать до и во время загрузки
- ✅ **Управление приоритетами** - изменение приоритета файлов в активной раздаче
- ✅ **Фоновый сервис** - непрерывная работа в фоне с foreground уведомлением
- ✅ **Постоянное уведомление** - нельзя закрыть пока активны загрузки
- ✅ **Персистентность** - сохранение состояния в Room database
- ✅ **Реактивность** - Flow API для мониторинга изменений
- ✅ **Полная статистика** - скорость, пиры, сиды, прогресс, ETA
- ✅ **Pause/Resume/Remove** - полный контроль над раздачами
## 📦 Установка
### 1. Добавьте модуль в `settings.gradle.kts`:
```kotlin
include(":torrentengine")
```
### 2. Добавьте зависимость в `app/build.gradle.kts`:
```kotlin
dependencies {
    implementation(project(":torrentengine"))
}
```
### 3. Добавьте permissions в `AndroidManifest.xml`:
```xml
```
## 🚀 Использование
### Инициализация
```kotlin
val torrentEngine = TorrentEngine.getInstance(context)
torrentEngine.startStatsUpdater() // Запустить обновление статистики
```
### Добавление торрента
```kotlin
lifecycleScope.launch {
    try {
        val magnetUri = "magnet:?xt=urn:btih:..."
        val savePath = "${context.getExternalFilesDir(null)}/downloads"
        
        val infoHash = torrentEngine.addTorrent(magnetUri, savePath)
        Log.d("Torrent", "Added: $infoHash")
    } catch (e: Exception) {
        Log.e("Torrent", "Failed to add", e)
    }
}
```
### Получение списка торрентов (реактивно)
```kotlin
lifecycleScope.launch {
    torrentEngine.getAllTorrentsFlow().collect { torrents ->
        torrents.forEach { torrent ->
            println("${torrent.name}: ${torrent.progress * 100}%")
            println("Speed: ${torrent.downloadSpeed} B/s")
            println("Peers: ${torrent.numPeers}, Seeds: ${torrent.numSeeds}")
            println("ETA: ${torrent.getFormattedEta()}")
        }
    }
}
```
### Управление файлами в раздаче
```kotlin
lifecycleScope.launch {
    // Получить информацию о торренте
    val torrent = torrentEngine.getTorrent(infoHash)
    
    torrent?.files?.forEachIndexed { index, file ->
        println("File $index: ${file.path} (${file.size} bytes)")
        
        // Выбрать только видео файлы
        if (file.isVideo()) {
            torrentEngine.setFilePriority(infoHash, index, FilePriority.HIGH)
        } else {
            torrentEngine.setFilePriority(infoHash, index, FilePriority.DONT_DOWNLOAD)
        }
    }
}
```
### Пауза/Возобновление/Удаление
```kotlin
lifecycleScope.launch {
    // Поставить на паузу
    torrentEngine.pauseTorrent(infoHash)
    
    // Возобновить
    torrentEngine.resumeTorrent(infoHash)
    
    // Удалить (с файлами или без)
    torrentEngine.removeTorrent(infoHash, deleteFiles = true)
}
```
### Множественное изменение приоритетов
```kotlin
lifecycleScope.launch {
    val priorities = mapOf(
        0 to FilePriority.MAXIMUM,  // Первый файл - максимальный приоритет
        1 to FilePriority.HIGH,      // Второй - высокий
        2 to FilePriority.DONT_DOWNLOAD // Третий - не загружать
    )
    
    torrentEngine.setFilePriorities(infoHash, priorities)
}
```
## 📊 Модели данных
### TorrentInfo
```kotlin
data class TorrentInfo(
    val infoHash: String,
    val magnetUri: String,
    val name: String,
    val totalSize: Long,
    val downloadedSize: Long,
    val uploadedSize: Long,
    val downloadSpeed: Int,
    val uploadSpeed: Int,
    val progress: Float,
    val state: TorrentState,
    val numPeers: Int,
    val numSeeds: Int,
    val savePath: String,
    val files: List,
    val addedDate: Long,
    val finishedDate: Long?,
    val error: String?
)
```
### TorrentState
```kotlin
enum class TorrentState {
    STOPPED,
    QUEUED,
    METADATA_DOWNLOADING,
    CHECKING,
    DOWNLOADING,
    SEEDING,
    FINISHED,
    ERROR
}
```
### FilePriority
```kotlin
enum class FilePriority(val value: Int) {
    DONT_DOWNLOAD(0),  // Не загружать
    LOW(1),            // Низкий приоритет
    NORMAL(4),         // Обычный (по умолчанию)
    HIGH(6),           // Высокий
    MAXIMUM(7)         // Максимальный (загружать первым)
}
```
## 🔔 Foreground Service
Сервис автоматически запускается при добавлении торрента и показывает постоянное уведомление с:
- Количеством активных торрентов
- Общей скоростью загрузки/отдачи
- Списком загружающихся файлов с прогрессом
- Кнопками управления (Pause All)
Уведомление **нельзя закрыть** пока есть активные торренты.
## 💾 Персистентность
Все торренты сохраняются в Room database и автоматически восстанавливаются при перезапуске приложения.
## 🔧 Расширенные возможности
### Проверка видео файлов
```kotlin
val videoFiles = torrent.files.filter { it.isVideo() }
```
### Получение share ratio
```kotlin
val ratio = torrent.getShareRatio()
```
### Подсчет выбранных файлов
```kotlin
val selectedCount = torrent.getSelectedFilesCount()
val selectedSize = torrent.getSelectedSize()
```
## 📱 Интеграция с Flutter
Создайте MethodChannel для вызова из Flutter:
```kotlin
class TorrentEngineChannel(private val context: Context) {
    private val torrentEngine = TorrentEngine.getInstance(context)
    private val channel = "com.neomovies/torrent"
    
    fun setupMethodChannel(flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "addTorrent" -> {
                        val magnetUri = call.argument("magnetUri")!!
                        val savePath = call.argument("savePath")!!
                        
                        CoroutineScope(Dispatchers.IO).launch {
                            try {
                                val hash = torrentEngine.addTorrent(magnetUri, savePath)
                                result.success(hash)
                            } catch (e: Exception) {
                                result.error("ERROR", e.message, null)
                            }
                        }
                    }
                    // ... другие методы
                }
            }
    }
}
```
## 📄 Лицензия
MIT License - используйте свободно в любых проектах!
## 🤝 Вклад
Библиотека разработана как универсальное решение для работы с торрентами в Android.
Может использоваться в любых проектах без ограничений.
## 🐛 Известные проблемы
- LibTorrent4j требует минимум Android 5.0 (API 21)
- Для Android 13+ нужно запрашивать POST_NOTIFICATIONS permission
- Foreground service требует отображения уведомления
## 📞 Поддержка
При возникновении проблем создайте issue с описанием и логами.