Initial commit: docker compose config
Release Docker multi arch / docker (push) Has been cancelled
Test Install Script / Test Script Syntax (push) Has been cancelled
Test Install Script / Test on almalinux-10 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-10 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (root) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (default) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (root) (push) Has been cancelled
Test Install Script / Test on debian-11 (default) (push) Has been cancelled
Test Install Script / Test on debian-11 (root) (push) Has been cancelled
Test Install Script / Test on debian-12 (default) (push) Has been cancelled
Test Install Script / Test on debian-12 (root) (push) Has been cancelled
Test Install Script / Test on debian-13 (default) (push) Has been cancelled
Test Install Script / Test on debian-13 (root) (push) Has been cancelled
Test Install Script / Test on fedora-latest (default) (push) Has been cancelled
Test Install Script / Test on fedora-latest (root) (push) Has been cancelled
Test Install Script / Test on rocky-10 (default) (push) Has been cancelled
Test Install Script / Test on rocky-10 (root) (push) Has been cancelled
Test Install Script / Test on rocky-8 (default) (push) Has been cancelled
Test Install Script / Test on rocky-8 (root) (push) Has been cancelled
Test Install Script / Test on rocky-9 (default) (push) Has been cancelled
Test Install Script / Test on rocky-9 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (root) (push) Has been cancelled
Release Docker multi arch / docker (push) Has been cancelled
Test Install Script / Test Script Syntax (push) Has been cancelled
Test Install Script / Test on almalinux-10 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-10 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (root) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (default) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (root) (push) Has been cancelled
Test Install Script / Test on debian-11 (default) (push) Has been cancelled
Test Install Script / Test on debian-11 (root) (push) Has been cancelled
Test Install Script / Test on debian-12 (default) (push) Has been cancelled
Test Install Script / Test on debian-12 (root) (push) Has been cancelled
Test Install Script / Test on debian-13 (default) (push) Has been cancelled
Test Install Script / Test on debian-13 (root) (push) Has been cancelled
Test Install Script / Test on fedora-latest (default) (push) Has been cancelled
Test Install Script / Test on fedora-latest (root) (push) Has been cancelled
Test Install Script / Test on rocky-10 (default) (push) Has been cancelled
Test Install Script / Test on rocky-10 (root) (push) Has been cancelled
Test Install Script / Test on rocky-8 (default) (push) Has been cancelled
Test Install Script / Test on rocky-8 (root) (push) Has been cancelled
Test Install Script / Test on rocky-9 (default) (push) Has been cancelled
Test Install Script / Test on rocky-9 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (root) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
package tgbot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
tele "gopkg.in/telebot.v4"
|
||||
"server/dlna"
|
||||
"server/rutor"
|
||||
"server/settings"
|
||||
"server/torr"
|
||||
"server/torznab"
|
||||
)
|
||||
|
||||
const pendingInputTTL = 30 * time.Minute
|
||||
|
||||
type pendingInput struct {
|
||||
Setting string
|
||||
UserID int64
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
pendingInputMu sync.Mutex
|
||||
pendingInputs = make(map[string]pendingInput)
|
||||
)
|
||||
|
||||
func init() {
|
||||
go pendingInputCleanup()
|
||||
}
|
||||
|
||||
func pendingInputCleanup() {
|
||||
ticker := time.NewTicker(5 * time.Minute)
|
||||
for range ticker.C {
|
||||
pendingInputMu.Lock()
|
||||
now := time.Now()
|
||||
for key, p := range pendingInputs {
|
||||
if now.Sub(p.CreatedAt) > pendingInputTTL {
|
||||
delete(pendingInputs, key)
|
||||
}
|
||||
}
|
||||
pendingInputMu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func sendSettingsInputPrompt(c tele.Context, uid int64, setting, hint string) error {
|
||||
msg := fmt.Sprintf("✏️ %s\n\n%s", tr(uid, "settings_input_reply"), hint)
|
||||
btnCancel := tele.InlineButton{Text: "❌ " + tr(uid, "canceled"), Unique: "fset", Data: "input_cancel"}
|
||||
kbd := &tele.ReplyMarkup{InlineKeyboard: [][]tele.InlineButton{{btnCancel}}}
|
||||
sent, err := c.Bot().Send(c.Chat(), msg, kbd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pendingInputMu.Lock()
|
||||
pendingInputs[chatMsgKey(sent.Chat.ID, sent.ID)] = pendingInput{Setting: setting, UserID: uid, CreatedAt: time.Now()}
|
||||
pendingInputMu.Unlock()
|
||||
return c.Respond(&tele.CallbackResponse{})
|
||||
}
|
||||
|
||||
func handleSettingsInputReply(c tele.Context) (handled bool) {
|
||||
msg := c.Message()
|
||||
if msg.ReplyTo == nil {
|
||||
return false
|
||||
}
|
||||
key := chatMsgKey(msg.ReplyTo.Chat.ID, msg.ReplyTo.ID)
|
||||
pendingInputMu.Lock()
|
||||
pending, ok := pendingInputs[key]
|
||||
delete(pendingInputs, key)
|
||||
pendingInputMu.Unlock()
|
||||
if !ok || pending.UserID != msg.Sender.ID {
|
||||
return false
|
||||
}
|
||||
if time.Since(pending.CreatedAt) > pendingInputTTL {
|
||||
_ = c.Send(tr(msg.Sender.ID, "canceled"))
|
||||
return true
|
||||
}
|
||||
applySettingsInput(c, pending.Setting, strings.TrimSpace(msg.Text))
|
||||
return true
|
||||
}
|
||||
|
||||
func cancelSettingsInput(c tele.Context) error {
|
||||
key := chatMsgKey(c.Callback().Message.Chat.ID, c.Callback().Message.ID)
|
||||
pendingInputMu.Lock()
|
||||
delete(pendingInputs, key)
|
||||
pendingInputMu.Unlock()
|
||||
_ = c.Bot().Delete(c.Callback().Message)
|
||||
return c.Respond(&tele.CallbackResponse{Text: tr(c.Sender().ID, "canceled")})
|
||||
}
|
||||
|
||||
func applySettingsInput(c tele.Context, setting, value string) {
|
||||
uid := c.Sender().ID
|
||||
if !isAdmin(uid) {
|
||||
_ = c.Send(tr(uid, "admin_only"))
|
||||
return
|
||||
}
|
||||
if settings.ReadOnly {
|
||||
_ = c.Send(tr(uid, "settings_readonly"))
|
||||
return
|
||||
}
|
||||
if settings.BTsets == nil {
|
||||
_ = c.Send(tr(uid, "settings_not_loaded"))
|
||||
return
|
||||
}
|
||||
|
||||
clear := strings.ToLower(value) == "clear" || strings.ToLower(value) == "очистить" || value == "-"
|
||||
if clear {
|
||||
value = ""
|
||||
}
|
||||
|
||||
sets := new(settings.BTSets)
|
||||
*sets = *settings.BTsets
|
||||
|
||||
switch setting {
|
||||
case "friendlyname":
|
||||
sets.FriendlyName = value
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "FriendlyName", valueOrClear(value)))
|
||||
case "torrentssavepath":
|
||||
if value != "" {
|
||||
abs, err := filepath.Abs(value)
|
||||
if err != nil {
|
||||
abs = value
|
||||
}
|
||||
if _, err := os.Stat(abs); err != nil && !os.IsNotExist(err) {
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_error"), err.Error()))
|
||||
return
|
||||
}
|
||||
sets.TorrentsSavePath = abs
|
||||
sets.UseDisk = true
|
||||
} else {
|
||||
sets.TorrentsSavePath = ""
|
||||
sets.UseDisk = false
|
||||
}
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "TorrentsSavePath", valueOrClear(value)))
|
||||
case "sslcert":
|
||||
sets.SslCert = value
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "SslCert", valueOrClear(value)))
|
||||
case "sslkey":
|
||||
sets.SslKey = value
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "SslKey", valueOrClear(value)))
|
||||
case "tmdbkey":
|
||||
sets.TMDBSettings.APIKey = value
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "TMDB API Key", valueOrClear(value)))
|
||||
case "proxyhosts":
|
||||
if value == "" {
|
||||
sets.ProxyHosts = nil
|
||||
} else {
|
||||
parts := strings.Split(value, ",")
|
||||
for i := range parts {
|
||||
parts[i] = strings.TrimSpace(parts[i])
|
||||
}
|
||||
sets.ProxyHosts = parts
|
||||
}
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_done"), "ProxyHosts", valueOrClear(value)))
|
||||
case "torznab_add":
|
||||
if value == "" {
|
||||
_ = c.Send(tr(uid, "settings_input_torznab_usage"))
|
||||
return
|
||||
}
|
||||
parts := strings.SplitN(value, "|", 3)
|
||||
cfg := settings.TorznabConfig{Host: strings.TrimSpace(parts[0])}
|
||||
if len(parts) > 1 {
|
||||
cfg.Key = strings.TrimSpace(parts[1])
|
||||
}
|
||||
if len(parts) > 2 {
|
||||
cfg.Name = strings.TrimSpace(parts[2])
|
||||
}
|
||||
if !strings.HasPrefix(cfg.Host, "http") {
|
||||
cfg.Host = "https://" + cfg.Host
|
||||
}
|
||||
sets.TorznabUrls = append(sets.TorznabUrls, cfg)
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_input_torznab_added"), cfg.Host))
|
||||
case "torznab_test":
|
||||
if value == "" {
|
||||
_ = c.Send(tr(uid, "settings_input_torznab_usage"))
|
||||
return
|
||||
}
|
||||
parts := strings.SplitN(value, "|", 3)
|
||||
host := strings.TrimSpace(parts[0])
|
||||
key := ""
|
||||
if len(parts) > 1 {
|
||||
key = strings.TrimSpace(parts[1])
|
||||
}
|
||||
if !strings.HasPrefix(host, "http") {
|
||||
host = "https://" + host
|
||||
}
|
||||
if err := torznab.Test(host, key); err != nil {
|
||||
_ = c.Send(fmt.Sprintf(tr(uid, "settings_torznab_test_fail"), err.Error()))
|
||||
return
|
||||
}
|
||||
_ = c.Send(tr(uid, "settings_torznab_test_ok"))
|
||||
return
|
||||
default:
|
||||
_ = c.Send(tr(uid, "callback_unknown"))
|
||||
return
|
||||
}
|
||||
|
||||
torr.SetSettings(sets)
|
||||
dlna.Stop()
|
||||
if sets.EnableDLNA {
|
||||
dlna.Start()
|
||||
}
|
||||
rutor.Stop()
|
||||
rutor.Start()
|
||||
}
|
||||
|
||||
func valueOrClear(v string) string {
|
||||
if v == "" {
|
||||
return "(cleared)"
|
||||
}
|
||||
if len(v) > 50 {
|
||||
return v[:47] + "..."
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user