mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-08-29 04:06:42 +08:00
* fix: prevent queue deadlock after cancelling tasks Get no longer recurses while holding the mutex. Cancelled queued tasks leave the map, making their IDs reusable. Closed empty queues return ErrQueueClosed. * fix: init task queue lazily and close on shutdown AddTask is safe before Run by initializing the queue once. Close unblocks workers waiting in Get. * fix: make resource fingerprints deterministic Sort map keys before hashing so Resource.ID is stable. * fix: harden per-item processing tracking in tasks Use the resource fingerprint as the dedup key on insert and delete. Check and set processing entries atomically instead of TOCTOU. Count only successful downloads. * fix: honor IgnoreErrors in batch tasks Element failures no longer cancel sibling elements or stop later groups. * fix: report streamed upload bytes in batch tasks Stream downloads report their byte count as the upload total. * fix: validate i18n key parity across locales geni18n fails when a language file misses any key. Align the syncpeers completion key between en and zh-Hans. Translate three untranslated parse keys in zh-Hans. * refactor: share progress throttling helpers Move size-tiered and count-based throttling into progressutil. Localize hardcoded Chinese progress strings. Drop five duplicated implementations and dead local copies. * refactor: share unique filename logic Storage backends use fsutil.UniquePath instead of local loops. * fix: sanitize local storage paths Reject absolute paths and dot-dot escapes in Save. Check close errors and wrap creation failures. * fix: preserve webdav error causes Wrap mkdir and write failures with %w and drop dead error values. * fix: kill rclone subprocess on reader close Prevent cat processes from hanging after the pipe is closed. * fix: fail alist init instead of exiting Replace log.Fatalf with wrapped errors so a bad alist cannot kill the bot. Cancel token refresh with the init context and re-login on 401. * fix: enforce telegram album limits and track saved paths Use tglimit.MaxAlbumItems for album batching and video splitting. Exists now reports previously saved paths instead of always false. * fix: guard storage registry maps Protect Storages and UserStorages with mutexes and expose read accessors. * fix: harden JS parser plugin runtime Validate semver instead of panicking and require canHandle. Recover plugin worker panics and time out CanHandle calls. Return a copy from the registry and sanitize install filenames. * fix: guard kemono parser against nil fields Skip sparse preview and attachment entries instead of panicking. * refactor: remove commented-out dead code Drop unused kemono legacy types and commented response structs. * test: cover invalid plugin version rejection * fix: show all queued tasks in /task list Render up to ten tasks and append the truncation note once. * fix: guard callback data parsing Reject malformed callback payloads before indexing split parts. * fix: isolate media groups per user Key pending groups by chat, user and group id. * fix: require permission for callback handlers * fix: initialize userbot context once Replace the racy lazy init with sync.OnceValue. * fix: avoid leaking raw errors in /dir reply * fix: notify users on invalid update version * fix: fail fast when API listen fails Bind synchronously and surface errors instead of logging them. * fix: add timeouts and backoff to webhook delivery * refactor: remove dead code from api and bot Drop the empty ProgressTracker shim, unused token context key and a redundant SetBotCommands call. * fix: load remote config without local lookup Skip the local file search after reading a config URL and add a timeout. * refactor: drop unused hook config * docs: document parser plugin config * ci: fix BuildTime formatting and align checkout Actions format does not format dates; pass the raw timestamp. * chore: ignore cache directory * fix: make cache init idempotent * fix: upload only downloaded batch elements Failed elements keep partial cache files and never reach the backend. Successfully downloaded siblings still upload when one element fails. * fix: record telegram saved paths only after upload Skip-large returns a sentinel so skipped files are not marked as saved. * fix: deduplicate alist token refreshes Guard token access with a mutex and merge concurrent logins. Reuse a recent refresh to avoid login storms. * test: cover concurrent alist 401 retry Ten parallel uploads share a single re-login under -race. * fix: count parsed resources in progress text * fix: localize storage lookup errors in /dir Use the shared i18n key and escape the dynamic error. * fix: deduplicate concurrent storage initialization singleflight merges first-time inits so side effects are not duplicated. * fix: guard nil progress trackers in api-created tasks Batch, telegraph and transfer tasks run without a Telegram tracker when created through the API; their callbacks must not panic. * fix: keep album order when filtering failed batch items Download results are stored by original index so surviving elements keep their source order. * test: cover nil-tracker task execution * fix: report partial failure in batch done message IgnoreErrors runs with failed elements show success and failed counts instead of claiming every file completed. * fix: skip login refresh for token-only alist storage 401 responses surface the auth error instead of sending a credential-less login; the refresh window never exceeds TokenExp. * test: cover alist refresh semantics Concurrent refresh uses username/password; token-only storage never attempts a login on 401. * fix: call tracker from notifyProgress instead of recursing The helper called itself, overflowing the stack on any batch task with a progress tracker. * fix: propagate cancellation past IgnoreErrors Cancelled tasks must not be reported as successful: only ordinary element failures are ignored. * test: cover notifyProgress tracker call * test: cover cancellation with IgnoreErrors * fix: refresh alist token after startup 401s The init login no longer satisfies the dedup window, so an early 401 triggers a real refresh; later 401s reuse it. Clarify that streaming uploads cannot replay their body. * test: exercise the alist 401 refresh path Concurrent uploads now reject the init token, share one refresh and retry with the new token; token-only stays inert. * style: trim verbose comments Drop process-style explanations; keep one-line behavior notes. * style: gofmt test files * fix: drop unbounded saved-path cache in telegram storage Telegram cannot reliably query remote file existence, so the cache answered a question it could not answer and grew without bound. Exists returns false again, as before. * style: format codes
111 lines
3.2 KiB
TOML
111 lines
3.2 KiB
TOML
# 创建文件时,若需要保留中文注释,请务必确保本文件编码为 UTF-8 ,否则会无法读取。
|
|
# 更详细的配置请在 https://sabot.unv.app/deployment/configuration 查看
|
|
workers = 4 # 同时下载文件数
|
|
retry = 3 # 下载失败重试次数
|
|
threads = 4 # 单个任务下载使用的最大线程数
|
|
stream = false # 使用流式传输模式, 建议仅在硬盘空间十分有限时使用.
|
|
|
|
[log]
|
|
# 日志级别, 可选: debug, info, warn, error, fatal
|
|
level = "debug"
|
|
|
|
[telegram]
|
|
# Bot Token
|
|
# 更换 Bot Token 后请删除会话数据库文件 (默认路径为 data/session.db )
|
|
token = ""
|
|
# Telegram API 配置, 若不配置也可运行, 将使用默认的 API ID 和 API HASH
|
|
# 推荐使用自己的 API ID 和 API HASH (https://my.telegram.org)
|
|
# app_id = 1025907
|
|
# app_hash = "452b0359b988148995f22ff0f4229750"
|
|
[telegram.proxy]
|
|
# 启用代理连接 telegram
|
|
enable = false
|
|
url = "socks5://127.0.0.1:7890"
|
|
|
|
# Aria2 配置
|
|
[aria2]
|
|
# 启用 Aria2 下载支持
|
|
enable = false
|
|
# Aria2 RPC URL
|
|
url = "http://localhost:6800/jsonrpc"
|
|
# Aria2 RPC Secret (如果配置了 rpc-secret)
|
|
secret = ""
|
|
# 转存完成后删除 Aria2 下载的本地文件
|
|
remove_after_transfer = true
|
|
|
|
# yt-dlp 视频下载配置
|
|
[ytdlp]
|
|
# 默认下载的最高视频清晰度 (按高度限制), 如 1080, 720, 480; 0 表示不限制 (下载最佳画质)
|
|
# 仅在使用 /ytdlp 命令且未手动指定任何参数时生效
|
|
max_height = 1080
|
|
# 直接指定 yt-dlp format 选择表达式, 留空则使用 max_height
|
|
# 设置后优先级高于 max_height, 例如: "bv*[height<=720]+ba/b"
|
|
format = ""
|
|
# 下载后转封装的视频容器格式, 留空则不转封装. 默认 mp4
|
|
recode = "mp4"
|
|
|
|
# 解析器配置
|
|
[parser]
|
|
# 启用 JS 解析器插件 (Go 内置解析器默认启用)
|
|
plugin_enable = false
|
|
# 插件目录, 可以是多个目录
|
|
plugin_dirs = ["./plugins"]
|
|
# 解析器默认代理
|
|
proxy = ""
|
|
|
|
# Twitter/X 解析器配置
|
|
[parser.twitter]
|
|
# 自定义 API 域名
|
|
api_domain = "api.fxtwitter.com"
|
|
# 单独为此解析器指定代理 (留空则使用 [parser] 中的 proxy)
|
|
# proxy = "http://127.0.0.1:7890"
|
|
|
|
# Kemono 解析器配置 (暂无可配置项, 留空即可)
|
|
[parser.kemono]
|
|
|
|
# HTTP API 配置
|
|
[api]
|
|
# 启用 HTTP API
|
|
enable = false
|
|
# 监听地址
|
|
host = "0.0.0.0"
|
|
# 监听端口
|
|
port = 8080
|
|
# 认证 Token (必需)
|
|
token = ""
|
|
|
|
# 存储列表
|
|
[[storages]]
|
|
# 标识名, 需要唯一
|
|
name = "本机1"
|
|
# 存储类型, 目前可用: local, alist, webdav, s3, telegram
|
|
type = "local"
|
|
# 启用存储
|
|
enable = true
|
|
# 文件保存根路径
|
|
base_path = "./downloads"
|
|
|
|
[[storages]]
|
|
name = "MyWebdav"
|
|
type = "webdav"
|
|
enable = false
|
|
base_path = '/path/telegram'
|
|
url = 'https://example.com/dav'
|
|
username = 'username'
|
|
password = 'password'
|
|
|
|
# 用户列表
|
|
[[users]]
|
|
# telegram user id
|
|
id = 114514
|
|
# 存储过滤列表, 元素为存储标识名.
|
|
# 将该列表留空并开启黑名单过滤模式以允许使用所有存储,此处示例为黑名单模式,用户 114514 可使用所有存储
|
|
storages = []
|
|
# 使用列表过滤黑名单模式,反之则为白名单,白名单请在列表中指定可用的存储.
|
|
blacklist = true
|
|
|
|
[[users]]
|
|
id = 123456
|
|
storages = ["本机1"]
|
|
blacklist = false # 使用白名单模式,此时,用户 123456 仅可使用标识名为 '本地1' 的存储
|