Добавлен мониторинг завершения торрентов через RPC‑опрос
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
Добавлена функция monitorTorrentCompletion для проверки состояния торрента каждые 10 секунд. Добавлена структура torrentState для отслеживания состояния торрентов и определения их завершения. Обновлена основная логика для работы с chat ID при отправке уведомлений. Улучшен README — добавлены сведения об автоматических уведомлениях о завершении загрузки и методах мониторинга.
This commit is contained in:
198
README.md
198
README.md
@@ -1,39 +1,38 @@
|
|||||||
# transmission-telegram
|
# transmission-telegram
|
||||||
|
|
||||||
#### Manage your transmission through Telegram.
|
#### Управляйте Transmission через Telegram.
|
||||||
|
|
||||||
<img src="https://raw.github.com/pyed/transmission-telegram/master/demo.gif" width="400" />
|
<img src="https://raw.github.com/pyed/transmission-telegram/master/demo.gif" width="400" />
|
||||||
|
|
||||||
## CLI
|
## CLI
|
||||||
|
|
||||||
### Install
|
### Установка
|
||||||
|
|
||||||
Just [download](https://github.com/pyed/transmission-telegram/releases) the appropriate binary for your OS, place `transmission-telegram` in your `$PATH` and you are good to go.
|
Просто [скачайте](https://github.com/pyed/transmission-telegram/releases) подходящий бинарный файл для вашей ОС, поместите `transmission-telegram` в ваш `$PATH` и готово.
|
||||||
|
|
||||||
Or if you have `Go` installed: `go get -u github.com/pyed/transmission-telegram`
|
Или, если у вас установлен `Go`: `go get -u github.com/pyed/transmission-telegram`
|
||||||
|
|
||||||
## Usage
|
## Использование
|
||||||
|
|
||||||
[Wiki](https://github.com/pyed/transmission-telegram/wiki)
|
[Wiki](https://github.com/pyed/transmission-telegram/wiki)
|
||||||
|
|
||||||
|
## Установка через Docker
|
||||||
## Docker Alternate Installation Route
|
|
||||||
|
|
||||||
### Standalone
|
### Standalone
|
||||||
|
|
||||||
```
|
```bash
|
||||||
docker run -d --name transmission-telegram \
|
docker run -d --name transmission-telegram \
|
||||||
kevinhalpin/transmission-telegram:latest \
|
kevinhalpin/transmission-telegram:latest \
|
||||||
-token=<Your Bot Token> \
|
-token=<Ваш Токен Бота> \
|
||||||
-master=<Your Username> \
|
-master=<Ваш Username> \
|
||||||
-url=<Transmission RPC> \
|
-url=<Transmission RPC> \
|
||||||
-username=<Transmission If Needed> \
|
-username=<Transmission Если Нужно> \
|
||||||
-password=<Transmissions If Needed>
|
-password=<Transmission Если Нужно>
|
||||||
```
|
```
|
||||||
|
|
||||||
### docker-compose Example
|
### Пример docker-compose
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
version: '2.4'
|
version: '2.4'
|
||||||
services:
|
services:
|
||||||
transmission:
|
transmission:
|
||||||
@@ -57,5 +56,174 @@ telegram-transmission-bot:
|
|||||||
- emby
|
- emby
|
||||||
network_mode: 'host'
|
network_mode: 'host'
|
||||||
image: kevinhalpin/transmission-telegram:latest
|
image: kevinhalpin/transmission-telegram:latest
|
||||||
command: '-token=${TELEGRAM_TRANSMISSION_BOT} -master=${TELEGRAM_USERNAME} -url=${TRANSMISSION_URL} - username=${TRANSMISSION_USERNAME} -password=${PASS}'
|
command: '-token=${TELEGRAM_TRANSMISSION_BOT} -master=${TELEGRAM_USERNAME} -url=${TRANSMISSION_URL} -username=${TRANSMISSION_USERNAME} -password=${PASS}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
Этот проект представляет собой Telegram-бота для управления клиентом BitTorrent Transmission. Бот позволяет:
|
||||||
|
|
||||||
|
- **Просмотр торрентов**: список всех торрентов, фильтрация по статусу (загрузка, раздача, на паузе, проверка), поиск по имени или трекеру
|
||||||
|
- **Управление торрентами**: добавление (по URL, magnet-ссылке или файлу .torrent), запуск, остановка, удаление, проверка целостности
|
||||||
|
- **Мониторинг**: просмотр статистики, скорости загрузки/отдачи, информации о конкретных торрентах с live-обновлениями
|
||||||
|
- **Настройки**: установка лимитов скорости, изменение директории загрузки, сортировка торрентов
|
||||||
|
- **Уведомления**: автоматические уведомления о завершении загрузок через мониторинг RPC API (работает автоматически, без дополнительной настройки)
|
||||||
|
|
||||||
|
Бот работает только с авторизованными пользователями (masters), что обеспечивает безопасность управления вашими торрентами.
|
||||||
|
|
||||||
|
## Настройка уведомлений о завершении загрузок
|
||||||
|
|
||||||
|
Бот автоматически отправляет уведомления в Telegram, когда торрент завершает загрузку. Для этого используется **мониторинг через RPC API** (рекомендуемый метод), который работает без дополнительной настройки.
|
||||||
|
|
||||||
|
### Метод 1: Мониторинг через RPC API (рекомендуется) ⭐
|
||||||
|
|
||||||
|
Этот метод работает автоматически и не требует дополнительной настройки. Бот периодически опрашивает Transmission через RPC API и отслеживает изменение статуса торрентов с "Загрузка" на "Раздача".
|
||||||
|
|
||||||
|
#### Как это работает
|
||||||
|
|
||||||
|
1. **Автоматический запуск**: Мониторинг запускается автоматически при старте бота
|
||||||
|
2. **Polling**: Бот опрашивает статус торрентов каждые 10 секунд через RPC API
|
||||||
|
3. **Обнаружение завершения**: При переходе торрента из статуса "Downloading" в "Seeding" (или при достижении 100% загрузки) отправляется уведомление
|
||||||
|
4. **Активация**: Отправьте боту любое сообщение (например, `/help`), чтобы он запомнил ваш chat ID для отправки уведомлений
|
||||||
|
|
||||||
|
#### Преимущества
|
||||||
|
|
||||||
|
- ✅ Не требует доступа к файловой системе
|
||||||
|
- ✅ Не требует настройки логирования в Transmission
|
||||||
|
- ✅ Работает в любой конфигурации (Docker, standalone, и т.д.)
|
||||||
|
- ✅ Более надежный и быстрый метод
|
||||||
|
- ✅ Не зависит от формата логов
|
||||||
|
|
||||||
|
#### Пример уведомления
|
||||||
|
|
||||||
|
Когда торрент завершит загрузку, вы получите сообщение вида:
|
||||||
|
```
|
||||||
|
✅ Completed: My-Torrent-Name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Метод 2: Мониторинг через лог-файл (альтернативный)
|
||||||
|
|
||||||
|
Альтернативный метод - мониторинг лог-файла Transmission. Этот метод требует дополнительной настройки, но может быть полезен в некоторых случаях.
|
||||||
|
|
||||||
|
#### Шаг 1: Включение логирования в Transmission
|
||||||
|
|
||||||
|
1. Откройте настройки Transmission (через веб-интерфейс или конфигурационный файл `settings.json`)
|
||||||
|
2. Включите логирование, установив параметр `"message-level": 2` (или выше) в `settings.json`
|
||||||
|
3. Убедитесь, что логирование включено: `"logging-enabled": true`
|
||||||
|
|
||||||
|
Для Docker-контейнера Transmission (linuxserver/transmission) логи обычно находятся в:
|
||||||
|
- `/config/transmission.log` (внутри контейнера)
|
||||||
|
- `${CONFIG}/transmission/transmission.log` (на хосте, если смонтирован volume)
|
||||||
|
|
||||||
|
**Пример настройки в `settings.json`:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"logging-enabled": true,
|
||||||
|
"message-level": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Шаг 2: Настройка бота для мониторинга логов
|
||||||
|
|
||||||
|
Добавьте параметр `-transmission-logfile` с путем к лог-файлу Transmission при запуске бота.
|
||||||
|
|
||||||
|
#### Для CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
transmission-telegram \
|
||||||
|
-token=<Ваш Токен Бота> \
|
||||||
|
-master=<Ваш Username> \
|
||||||
|
-url=<Transmission RPC> \
|
||||||
|
-transmission-logfile=/path/to/transmission.log
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Для Docker Standalone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name transmission-telegram \
|
||||||
|
-v /path/to/transmission.log:/transmission.log:ro \
|
||||||
|
kevinhalpin/transmission-telegram:latest \
|
||||||
|
-token=<Ваш Токен Бота> \
|
||||||
|
-master=<Ваш Username> \
|
||||||
|
-url=<Transmission RPC> \
|
||||||
|
-transmission-logfile=/transmission.log
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Для docker-compose:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2.4'
|
||||||
|
services:
|
||||||
|
transmission:
|
||||||
|
container_name: transmission
|
||||||
|
environment:
|
||||||
|
- PUID=${PUID_DOCKUSER}
|
||||||
|
- PGID=${PGID_APPZ}
|
||||||
|
image: linuxserver/transmission
|
||||||
|
network_mode: 'host'
|
||||||
|
hostname: 'transmission'
|
||||||
|
volumes:
|
||||||
|
- ${CONFIG}/transmission:/config
|
||||||
|
- ${DATA}/transmission/downloads:/downloads
|
||||||
|
|
||||||
|
telegram-transmission-bot:
|
||||||
|
container_name: telegram-transmission-bot
|
||||||
|
restart: on-failure
|
||||||
|
depends_on:
|
||||||
|
- transmission
|
||||||
|
network_mode: 'host'
|
||||||
|
image: kevinhalpin/transmission-telegram:latest
|
||||||
|
volumes:
|
||||||
|
- ${CONFIG}/transmission/transmission.log:/transmission.log:ro
|
||||||
|
command: >
|
||||||
|
-token=${TELEGRAM_TRANSMISSION_BOT}
|
||||||
|
-master=${TELEGRAM_USERNAME}
|
||||||
|
-url=${TRANSMISSION_URL}
|
||||||
|
-username=${TRANSMISSION_USERNAME}
|
||||||
|
-password=${PASS}
|
||||||
|
-transmission-logfile=/transmission.log
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Шаг 3: Активация уведомлений
|
||||||
|
|
||||||
|
**Важно**: После запуска бота с параметром `-transmission-logfile`, отправьте боту любое сообщение (например, `/help` или `list`). Это необходимо для того, чтобы бот запомнил ваш chat ID и мог отправлять уведомления.
|
||||||
|
|
||||||
|
#### Как это работает
|
||||||
|
|
||||||
|
Бот мониторит указанный лог-файл в реальном времени и ищет строки с паттерном `"Incomplete" to "Complete"`, которые Transmission записывает при завершении загрузки торрента. При обнаружении такой строки бот автоматически извлекает имя завершенного торрента и отправляет уведомление в Telegram.
|
||||||
|
|
||||||
|
**Пример строки в логе Transmission:**
|
||||||
|
```
|
||||||
|
[2017-02-22 21:00:00.898] My-Torrent-Name State changed from "Incomplete" to "Complete" (torrent.c:2218)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Устранение проблем
|
||||||
|
|
||||||
|
#### Устранение проблем (метод через лог-файл)
|
||||||
|
|
||||||
|
- **Уведомления не приходят**:
|
||||||
|
- Убедитесь, что логирование включено в Transmission (`logging-enabled: true`)
|
||||||
|
- Проверьте, что путь к лог-файлу указан правильно
|
||||||
|
- Убедитесь, что бот имеет доступ на чтение к лог-файлу
|
||||||
|
- Отправьте боту сообщение после запуска, чтобы он запомнил ваш chat ID
|
||||||
|
|
||||||
|
- **Лог-файл не найден**:
|
||||||
|
- Проверьте путь к файлу в настройках Transmission
|
||||||
|
- Для Docker: убедитесь, что volume с лог-файлом смонтирован правильно
|
||||||
|
- Проверьте права доступа к файлу
|
||||||
|
|
||||||
|
- **Бот не видит изменения в логе**:
|
||||||
|
- Убедитесь, что Transmission действительно пишет в указанный файл
|
||||||
|
- Проверьте уровень логирования (`message-level` должен быть 2 или выше)
|
||||||
|
|
||||||
|
#### Устранение проблем (метод через RPC API)
|
||||||
|
|
||||||
|
- **Уведомления не приходят**:
|
||||||
|
- Убедитесь, что бот имеет доступ к Transmission RPC API
|
||||||
|
- Проверьте, что Transmission работает и доступен по указанному URL
|
||||||
|
- Отправьте боту сообщение после запуска, чтобы он запомнил ваш chat ID
|
||||||
|
- Проверьте логи бота на наличие ошибок подключения к Transmission
|
||||||
|
|
||||||
|
- **Задержка уведомлений**:
|
||||||
|
- Бот опрашивает статус каждые 10 секунд, поэтому может быть небольшая задержка
|
||||||
|
- Это нормальное поведение и не требует настройки
|
||||||
|
|||||||
80
main.go
80
main.go
@@ -134,6 +134,9 @@ var (
|
|||||||
// chatID will be used to keep track of which chat to send completion notifictions.
|
// chatID will be used to keep track of which chat to send completion notifictions.
|
||||||
chatID int64
|
chatID int64
|
||||||
|
|
||||||
|
// torrentState stores previous state of torrents for completion detection
|
||||||
|
torrentStates = make(map[int]torrentState)
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
logger = log.New(os.Stdout, "", log.LstdFlags)
|
logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||||
|
|
||||||
@@ -151,6 +154,12 @@ var (
|
|||||||
"`", "'")
|
"`", "'")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// torrentState stores the state of a torrent for completion detection
|
||||||
|
type torrentState struct {
|
||||||
|
Status int
|
||||||
|
PercentDone float64
|
||||||
|
}
|
||||||
|
|
||||||
// we need a type for masters for the flag package to parse them as a slice
|
// we need a type for masters for the flag package to parse them as a slice
|
||||||
type masterSlice []string
|
type masterSlice []string
|
||||||
|
|
||||||
@@ -303,6 +312,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Start torrent completion monitoring via RPC polling
|
||||||
|
go monitorTorrentCompletion()
|
||||||
|
|
||||||
for update := range Updates {
|
for update := range Updates {
|
||||||
// ignore edited messages
|
// ignore edited messages
|
||||||
if update.Message == nil {
|
if update.Message == nil {
|
||||||
@@ -315,8 +327,8 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// update chatID for complete notification
|
// update chatID for complete notification (used by both log monitoring and RPC polling)
|
||||||
if TransLogFile != "" && chatID != update.Message.Chat.ID {
|
if chatID != update.Message.Chat.ID {
|
||||||
chatID = update.Message.Chat.ID
|
chatID = update.Message.Chat.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1537,6 +1549,70 @@ func getVersion(ud tgbotapi.Update) {
|
|||||||
send(fmt.Sprintf("Transmission *%s*\nTransmission-telegram *%s*", Client.Version(), VERSION), ud.Message.Chat.ID, true)
|
send(fmt.Sprintf("Transmission *%s*\nTransmission-telegram *%s*", Client.Version(), VERSION), ud.Message.Chat.ID, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// monitorTorrentCompletion monitors torrents via RPC API polling to detect completion
|
||||||
|
// It checks for status change from Downloading to Seeding, indicating completion
|
||||||
|
func monitorTorrentCompletion() {
|
||||||
|
// Polling interval - check every 10 seconds
|
||||||
|
ticker := time.NewTicker(10 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
logger.Printf("[INFO] Starting torrent completion monitoring via RPC polling")
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
// Skip if no chatID is set yet
|
||||||
|
if chatID == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current torrents
|
||||||
|
torrents, err := Client.GetTorrents()
|
||||||
|
if err != nil {
|
||||||
|
logger.Printf("[ERROR] Failed to get torrents for monitoring: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each torrent for completion
|
||||||
|
for _, torrent := range torrents {
|
||||||
|
prevState, exists := torrentStates[torrent.ID]
|
||||||
|
|
||||||
|
// Detect completion: transition from Downloading to Seeding with 100% done
|
||||||
|
completed := false
|
||||||
|
if exists && prevState.Status == transmission.StatusDownloading {
|
||||||
|
// Case 1: Status changed from Downloading to Seeding (most common)
|
||||||
|
if torrent.Status == transmission.StatusSeeding && torrent.PercentDone >= 1.0 {
|
||||||
|
completed = true
|
||||||
|
}
|
||||||
|
// Case 2: Torrent reached 100% while still in Downloading status
|
||||||
|
// (status might change to Seeding in next poll)
|
||||||
|
if torrent.Status == transmission.StatusDownloading &&
|
||||||
|
prevState.PercentDone < 1.0 &&
|
||||||
|
torrent.PercentDone >= 1.0 {
|
||||||
|
completed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if completed {
|
||||||
|
// Send completion notification
|
||||||
|
msg := fmt.Sprintf("✅ Completed: %s", torrent.Name)
|
||||||
|
send(msg, chatID, false)
|
||||||
|
logger.Printf("[INFO] Torrent completed: %s (ID: %d)", torrent.Name, torrent.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state - only track downloading torrents to save memory
|
||||||
|
if torrent.Status == transmission.StatusDownloading ||
|
||||||
|
torrent.Status == transmission.StatusDownloadPending {
|
||||||
|
torrentStates[torrent.ID] = torrentState{
|
||||||
|
Status: torrent.Status,
|
||||||
|
PercentDone: torrent.PercentDone,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Remove completed or stopped torrents from tracking
|
||||||
|
delete(torrentStates, torrent.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// send takes a chat id and a message to send, returns the message id of the send message
|
// send takes a chat id and a message to send, returns the message id of the send message
|
||||||
func send(text string, chatID int64, markdown bool) int {
|
func send(text string, chatID int64, markdown bool) int {
|
||||||
// set typing action
|
// set typing action
|
||||||
|
|||||||
Reference in New Issue
Block a user