Notify upon download completion

Introducing new flag "-transmission-logfile".

`transmission-daemon` should be started with '--logfile filename'
when `transmission-telegram` is pointed to that logfile via the new
flag, it should send a message upon any download completion.
This commit is contained in:
pyed 2017-02-24 00:36:30 +03:00
parent 098fa1d282
commit 6905f8a051

View File

@ -12,10 +12,10 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"gopkg.in/telegram-bot-api.v4"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/hpcloud/tail"
"github.com/pyed/transmission" "github.com/pyed/transmission"
"gopkg.in/telegram-bot-api.v4"
) )
const ( const (
@ -107,12 +107,13 @@ type stringslice []string
var ( var (
// flags // flags
BotToken string BotToken string
Masters stringslice Masters stringslice
RPCURL string RPCURL string
Username string Username string
Password string Password string
LogFile string LogFile string
TransLogFile string // Transmission log file
// transmission // transmission
Client *transmission.TransmissionClient Client *transmission.TransmissionClient
@ -121,6 +122,9 @@ var (
Bot *tgbotapi.BotAPI Bot *tgbotapi.BotAPI
Updates <-chan tgbotapi.Update Updates <-chan tgbotapi.Update
// chat id
chatID int64
// interval in seconds for live updates, affects: "active", "info", "speed", "head", "tail" // interval in seconds for live updates, affects: "active", "info", "speed", "head", "tail"
interval time.Duration = 2 interval time.Duration = 2
// duration controls how many intervals will happen // duration controls how many intervals will happen
@ -153,6 +157,7 @@ func init() {
flag.StringVar(&Username, "username", "", "Transmission username") flag.StringVar(&Username, "username", "", "Transmission username")
flag.StringVar(&Password, "password", "", "Transmission password") flag.StringVar(&Password, "password", "", "Transmission password")
flag.StringVar(&LogFile, "logfile", "", "Send logs to a file") flag.StringVar(&LogFile, "logfile", "", "Send logs to a file")
flag.StringVar(&TransLogFile, "transmission-logfile", "", "Open transmission logfile to monitor torrents completion")
// set the usage message // set the usage message
flag.Usage = func() { flag.Usage = func() {
@ -184,6 +189,39 @@ func init() {
log.SetOutput(logf) log.SetOutput(logf)
} }
// if we got a transmission log file, monitor it for torrents completion to notify upon them.
if TransLogFile != "" {
go func() {
ft, err := tail.TailFile(TransLogFile, tail.Config{
Location: &tail.SeekInfo{0, 2}, // ignore previous log lines
Follow: true, // tail -f
MustExist: true, // if you can't find the file, don't wait for it to be created.
})
if err != nil {
log.Printf("[ERROR] tailing transmission log: %s", err)
return
}
re := regexp.MustCompile(`"Incomplete" to "Complete"`)
// [2017-02-22 21:00:00.898] File-Name State changed from "Incomplete" to "Complete" (torrent.c:2218)
const start = len(`[2017-02-22 21:00:00.898] `)
const end = len(` State changed from "Incomplete" to "Complete" (torrent.c:2218)`)
for line := range ft.Lines {
// if we don't have a chatID continue
if chatID == 0 {
continue
}
if re.MatchString(line.Text) {
msg := fmt.Sprintf("Completed: %s", line.Text[start:len(line.Text)-end])
send(msg, chatID, false)
}
}
}()
}
// if the `-username` flag isn't set, look into the environment variable 'TR_AUTH' // if the `-username` flag isn't set, look into the environment variable 'TR_AUTH'
if Username == "" { if Username == "" {
if values := strings.Split(os.Getenv("TR_AUTH"), ":"); len(values) > 1 { if values := strings.Split(os.Getenv("TR_AUTH"), ":"); len(values) > 1 {
@ -241,6 +279,11 @@ func main() {
continue continue
} }
// update chatID for complete notification
if TransLogFile != "" && chatID != update.Message.Chat.ID {
chatID = update.Message.Chat.ID
}
// tokenize the update // tokenize the update
tokens := strings.Split(update.Message.Text, " ") tokens := strings.Split(update.Message.Text, " ")
command := strings.ToLower(tokens[0]) command := strings.ToLower(tokens[0])
@ -253,7 +296,7 @@ func main() {
go head(update, tokens[1:]) go head(update, tokens[1:])
case "tail", "/tail", "ta", "/ta": case "tail", "/tail", "ta", "/ta":
go tail(update, tokens[1:]) go tailf(update, tokens[1:])
case "downs", "/downs", "dl", "/dl": case "downs", "/downs", "dl", "/dl":
go downs(update) go downs(update)
@ -454,8 +497,8 @@ func head(ud tgbotapi.Update, tokens []string) {
} }
// tail lists the last 5 or n torrents // tailf lists the last 5 or n torrents
func tail(ud tgbotapi.Update, tokens []string) { func tailf(ud tgbotapi.Update, tokens []string) {
var ( var (
n = 5 // default to 5 n = 5 // default to 5
err error err error