|
|
|
|
@@ -15,7 +15,6 @@ import (
|
|
|
|
|
tgbotapi "gopkg.in/telegram-bot-api.v4"
|
|
|
|
|
"transmission-telegram/internal/config"
|
|
|
|
|
"transmission-telegram/internal/formatter"
|
|
|
|
|
"transmission-telegram/pkg/utils"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
@@ -76,7 +75,11 @@ func getCompiledRegex(pattern string) (*regexp.Regexp, error) {
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
return nil, fmt.Errorf("regex compilation timeout (pattern may be too complex): %s", pattern[:min(len(pattern), 50)])
|
|
|
|
|
patternPreview := pattern
|
|
|
|
|
if len(patternPreview) > 50 {
|
|
|
|
|
patternPreview = patternPreview[:50]
|
|
|
|
|
}
|
|
|
|
|
return nil, fmt.Errorf("regex compilation timeout (pattern may be too complex): %s", patternPreview)
|
|
|
|
|
case res := <-resultCh:
|
|
|
|
|
if res.err != nil {
|
|
|
|
|
return nil, fmt.Errorf("regex compilation error: %w", res.err)
|
|
|
|
|
@@ -86,8 +89,8 @@ func getCompiledRegex(pattern string) (*regexp.Regexp, error) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// min returns the minimum of two integers
|
|
|
|
|
func min(a, b int) int {
|
|
|
|
|
// minInt returns the minimum of two integers
|
|
|
|
|
func minInt(a, b int) int {
|
|
|
|
|
if a < b {
|
|
|
|
|
return a
|
|
|
|
|
}
|
|
|
|
|
@@ -117,7 +120,7 @@ func putBuffer(buf *bytes.Buffer) {
|
|
|
|
|
func (b *Bot) handleClientError(chatID int64, prefix string, err error) {
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.logger.Printf("[ERROR] %s: %v", prefix, err)
|
|
|
|
|
b.sendMessage(chatID, prefix+": "+err.Error(), false)
|
|
|
|
|
b.SendMessage(chatID, prefix+": "+err.Error(), false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -132,16 +135,16 @@ func (b *Bot) handleTorrentList(update tgbotapi.Update, errorPrefix, emptyMessag
|
|
|
|
|
buf := getBuffer()
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for i := range torrents {
|
|
|
|
|
if filter(&torrents[i]) {
|
|
|
|
|
buf.WriteString(format(&torrents[i]))
|
|
|
|
|
if filter(torrents[i]) {
|
|
|
|
|
buf.WriteString(format(torrents[i]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, emptyMessage, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, emptyMessage, false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handler methods for bot commands - these are placeholders that need full implementation
|
|
|
|
|
@@ -176,14 +179,14 @@ func (b *Bot) handleList(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
if len(tokens) != 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*list:* No tracker matches: *%s*", tokens[0]), true)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*list:* No tracker matches: *%s*", tokens[0]), true)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*list:* no torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*list:* no torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleHead(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
@@ -207,15 +210,15 @@ func (b *Bot) handleHead(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
buf := getBuffer()
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for i := range torrents[:n] {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(&torrents[i]))
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(torrents[i]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*head:* no torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*head:* no torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msgID := b.sendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
msgID := b.SendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
if !b.cfg.NoLive {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.cfg.Duration)*b.cfg.Interval+time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
@@ -249,15 +252,15 @@ func (b *Bot) handleTail(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
buf := getBuffer()
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for _, torrent := range torrents[len(torrents)-n:] {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(&torrent))
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(torrent))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*tail:* no torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*tail:* no torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msgID := b.sendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
msgID := b.SendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
if !b.cfg.NoLive {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.cfg.Duration)*b.cfg.Interval+time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
@@ -324,16 +327,16 @@ func (b *Bot) handleActive(update tgbotapi.Update) {
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for i := range torrents {
|
|
|
|
|
if torrents[i].RateDownload > 0 || torrents[i].RateUpload > 0 {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(&torrents[i]))
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(torrents[i]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "No active torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "No active torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msgID := b.sendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
msgID := b.SendMessage(update.Message.Chat.ID, buf.String(), true)
|
|
|
|
|
if !b.cfg.NoLive {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.cfg.Duration)*b.cfg.Interval+time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
@@ -353,7 +356,7 @@ func (b *Bot) handleErrors(update tgbotapi.Update) {
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleSort(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, `*sort* takes one of:
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, `*sort* takes one of:
|
|
|
|
|
(*id, name, age, size, progress, downspeed, upspeed, download, upload, ratio*)
|
|
|
|
|
optionally start with (*rev*) for reversed order
|
|
|
|
|
e.g. "*sort rev size*" to get biggest torrents first.`, true)
|
|
|
|
|
@@ -367,8 +370,8 @@ func (b *Bot) handleSort(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sortMap := map[string]struct {
|
|
|
|
|
normal transmission.SortType
|
|
|
|
|
rev transmission.SortType
|
|
|
|
|
normal transmission.Sorting
|
|
|
|
|
rev transmission.Sorting
|
|
|
|
|
}{
|
|
|
|
|
"id": {transmission.SortID, transmission.SortRevID},
|
|
|
|
|
"name": {transmission.SortName, transmission.SortRevName},
|
|
|
|
|
@@ -385,13 +388,13 @@ func (b *Bot) handleSort(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if sort, ok := sortMap[strings.ToLower(tokens[0])]; ok {
|
|
|
|
|
if reversed {
|
|
|
|
|
b.client.SetSort(sort.rev)
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*sort:* reversed "+tokens[0], false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*sort:* reversed "+tokens[0], false)
|
|
|
|
|
} else {
|
|
|
|
|
b.client.SetSort(sort.normal)
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*sort:* "+tokens[0], false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*sort:* "+tokens[0], false)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "unknown sorting method", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "unknown sorting method", false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -420,15 +423,15 @@ func (b *Bot) handleTrackers(update tgbotapi.Update) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "No trackers!", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "No trackers!", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleDownloadDir(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) < 1 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Please, specify a path for downloaddir", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Please, specify a path for downloaddir", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -441,16 +444,16 @@ func (b *Bot) handleDownloadDir(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if out.Result != "success" {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*downloaddir:* "+out.Result, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*downloaddir:* "+out.Result, false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*downloaddir:* downloaddir has been successfully changed to "+tokens[0], false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*downloaddir:* downloaddir has been successfully changed to "+tokens[0], false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleAdd(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*add:* needs at least one URL", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*add:* needs at least one URL", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -458,21 +461,21 @@ func (b *Bot) handleAdd(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
cmd := transmission.NewAddCmdByURL(url)
|
|
|
|
|
torrent, err := b.client.ExecuteAddCommand(cmd)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*add:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*add:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if torrent.Name == "" {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*add:* error adding "+url, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*add:* error adding "+url, false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*Added:* <%d> %s", torrent.ID, torrent.Name), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*Added:* <%d> %s", torrent.ID, torrent.Name), false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleSearch(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*search:* needs an argument", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*search:* needs an argument", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -493,15 +496,15 @@ func (b *Bot) handleSearch(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for i := range torrents {
|
|
|
|
|
if regx.MatchString(torrents[i].Name) {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentShort(&torrents[i]) + "\n")
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentShort(torrents[i]) + "\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "No matches!", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "No matches!", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleLatest(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
@@ -526,38 +529,38 @@ func (b *Bot) handleLatest(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
buf := getBuffer()
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
for i := range torrents[:n] {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentShort(&torrents[i]) + "\n")
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentShort(torrents[i]) + "\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if buf.Len() == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*latest:* No torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*latest:* No torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, buf.String(), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleInfo(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*info:* needs a torrent ID number", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*info:* needs a torrent ID number", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
torrentID, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*info:* %s is not a number", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*info:* %s is not a number", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
torrent, err := b.client.GetTorrent(torrentID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*info:* Can't find a torrent with an ID of %d", torrentID), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*info:* Can't find a torrent with an ID of %d", torrentID), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trackers := formatter.ExtractTrackers(torrent, trackerRegex)
|
|
|
|
|
info := formatter.FormatTorrentInfo(torrent, trackers)
|
|
|
|
|
msgID := b.sendMessage(update.Message.Chat.ID, info, true)
|
|
|
|
|
msgID := b.SendMessage(update.Message.Chat.ID, info, true)
|
|
|
|
|
|
|
|
|
|
if !b.cfg.NoLive {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.cfg.Duration)*b.cfg.Interval+time.Second)
|
|
|
|
|
@@ -569,109 +572,109 @@ func (b *Bot) handleInfo(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleStop(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*stop:* needs an argument", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*stop:* needs an argument", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tokens[0] == "all" {
|
|
|
|
|
if err := b.client.StopAll(); err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*stop:* error occurred while stopping some torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*stop:* error occurred while stopping some torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Stopped all torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Stopped all torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
num, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*stop:* %s is not a number", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*stop:* %s is not a number", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
status, err := b.client.StopTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*stop:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*stop:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
torrent, err := b.client.GetTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *stop:* No torrent with an ID of %d", num), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *stop:* No torrent with an ID of %d", num), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *stop:* %s", status, torrent.Name), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *stop:* %s", status, torrent.Name), false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleStart(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*start:* needs an argument", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*start:* needs an argument", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tokens[0] == "all" {
|
|
|
|
|
if err := b.client.StartAll(); err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*start:* error occurred while starting some torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*start:* error occurred while starting some torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Started all torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Started all torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
num, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*start:* %s is not a number", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*start:* %s is not a number", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
status, err := b.client.StartTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*start:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*start:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
torrent, err := b.client.GetTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *start:* No torrent with an ID of %d", num), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *start:* No torrent with an ID of %d", num), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *start:* %s", status, torrent.Name), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *start:* %s", status, torrent.Name), false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleCheck(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*check:* needs an argument", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*check:* needs an argument", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tokens[0] == "all" {
|
|
|
|
|
if err := b.client.VerifyAll(); err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*check:* error occurred while verifying some torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*check:* error occurred while verifying some torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Verifying all torrents", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Verifying all torrents", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
num, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*check:* %s is not a number", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*check:* %s is not a number", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
status, err := b.client.VerifyTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*check:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*check:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
torrent, err := b.client.GetTorrent(num)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *check:* No torrent with an ID of %d", num), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[fail] *check:* No torrent with an ID of %d", num), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *check:* %s", status, torrent.Name), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("[%s] *check:* %s", status, torrent.Name), false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -710,7 +713,7 @@ func (b *Bot) handleStats(update tgbotapi.Update) {
|
|
|
|
|
stats.CumulativeActiveTime(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, msg, true)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, msg, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleDownLimit(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
@@ -723,19 +726,19 @@ func (b *Bot) handleUpLimit(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleSpeedLimit(update tgbotapi.Update, tokens []string, limitType transmission.SpeedLimitType) {
|
|
|
|
|
if len(tokens) < 1 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Please, specify the limit", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Please, specify the limit", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
limit, err := strconv.ParseUint(tokens[0], 10, 32)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Please, specify the limit as number of kilobytes", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Please, specify the limit as number of kilobytes", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
speedLimitCmd := transmission.NewSpeedLimitCommand(limitType, uint(limit))
|
|
|
|
|
if speedLimitCmd == nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* internal error", limitType), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* internal error", limitType), false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -745,11 +748,11 @@ func (b *Bot) handleSpeedLimit(update tgbotapi.Update, tokens []string, limitTyp
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if out.Result != "success" {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* %v", limitType, out.Result), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* %v", limitType, out.Result), false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* limit has been successfully changed to %d KB/s", limitType, limit), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*%s:* limit has been successfully changed to %d KB/s", limitType, limit), false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleSpeed(update tgbotapi.Update) {
|
|
|
|
|
@@ -760,7 +763,7 @@ func (b *Bot) handleSpeed(update tgbotapi.Update) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msg := fmt.Sprintf("↓ %s ↑ %s", humanize.Bytes(stats.DownloadSpeed), humanize.Bytes(stats.UploadSpeed))
|
|
|
|
|
msgID := b.sendMessage(update.Message.Chat.ID, msg, false)
|
|
|
|
|
msgID := b.SendMessage(update.Message.Chat.ID, msg, false)
|
|
|
|
|
|
|
|
|
|
if !b.cfg.NoLive {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.cfg.Duration)*b.cfg.Interval+time.Second)
|
|
|
|
|
@@ -799,57 +802,57 @@ func (b *Bot) handleCount(update tgbotapi.Update) {
|
|
|
|
|
msg := fmt.Sprintf("Downloading: %d\nSeeding: %d\nPaused: %d\nVerifying: %d\n\n- Waiting to -\nDownload: %d\nSeed: %d\nVerify: %d\n\nTotal: %d",
|
|
|
|
|
downloading, seeding, stopped, checking, downloadingQ, seedingQ, checkingQ, len(torrents))
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, msg, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, msg, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleDel(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*del:* needs an ID", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*del:* needs an ID", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
num, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*del:* %s is not an ID", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*del:* %s is not an ID", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name, err := b.client.DeleteTorrent(num, false)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*del:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*del:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*Deleted:* "+name, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*Deleted:* "+name, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleDelData(update tgbotapi.Update, tokens []string) {
|
|
|
|
|
if len(tokens) == 0 {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*deldata:* needs an ID", false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*deldata:* needs an ID", false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, id := range tokens {
|
|
|
|
|
num, err := strconv.Atoi(id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("*deldata:* %s is not an ID", id), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("*deldata:* %s is not an ID", id), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name, err := b.client.DeleteTorrent(num, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*deldata:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*deldata:* "+err.Error(), false)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "Deleted with data: "+name, false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "Deleted with data: "+name, false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleVersion(update tgbotapi.Update) {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, fmt.Sprintf("Transmission *%s*\nTransmission-telegram *%s*", b.client.Version(), config.Version), true)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, fmt.Sprintf("Transmission *%s*\nTransmission-telegram *%s*", b.client.Version(), config.Version), true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (b *Bot) handleReceiveTorrent(update tgbotapi.Update) {
|
|
|
|
|
@@ -862,7 +865,7 @@ func (b *Bot) handleReceiveTorrent(update tgbotapi.Update) {
|
|
|
|
|
}
|
|
|
|
|
file, err := b.api.GetFile(fconfig)
|
|
|
|
|
if err != nil {
|
|
|
|
|
b.sendMessage(update.Message.Chat.ID, "*receiver:* "+err.Error(), false)
|
|
|
|
|
b.SendMessage(update.Message.Chat.ID, "*receiver:* "+err.Error(), false)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -893,7 +896,7 @@ func (b *Bot) liveUpdateTorrents(ctx context.Context, chatID int64, msgID int, f
|
|
|
|
|
defer putBuffer(buf)
|
|
|
|
|
|
|
|
|
|
for i := range filtered {
|
|
|
|
|
buf.WriteString(formatter(&filtered[i]))
|
|
|
|
|
buf.WriteString(formatter(filtered[i]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rate limit before sending
|
|
|
|
|
@@ -924,7 +927,7 @@ func (b *Bot) liveUpdateActive(ctx context.Context, chatID int64, msgID int) {
|
|
|
|
|
buf := getBuffer()
|
|
|
|
|
for i := range torrents {
|
|
|
|
|
if torrents[i].RateDownload > 0 || torrents[i].RateUpload > 0 {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(&torrents[i]))
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentDetailed(torrents[i]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -956,7 +959,7 @@ func (b *Bot) liveUpdateActive(ctx context.Context, chatID int64, msgID int) {
|
|
|
|
|
|
|
|
|
|
for i := range torrents {
|
|
|
|
|
if torrents[i].RateDownload > 0 || torrents[i].RateUpload > 0 {
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentActiveStopped(&torrents[i]))
|
|
|
|
|
buf.WriteString(formatter.FormatTorrentActiveStopped(torrents[i]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|