Добавил обновление библиотеки jellyfin после добавления медиа

This commit is contained in:
2026-06-15 07:33:21 +03:00
parent fff0960915
commit 093211c9c7
9 changed files with 283 additions and 4 deletions
+93
View File
@@ -0,0 +1,93 @@
// Package jellyfin — минимальный клиент Jellyfin для пересканирования
// медиатеки после успешной раскладки. Единственная задача: дёрнуть скан
// всех библиотек (POST /Library/Refresh), чтобы новые хардлинки быстрее
// появились в проигрывателе. В духе сервиса — без зоопарка вызовов.
package jellyfin
import (
"context"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"strings"
"time"
)
const defaultTimeout = 10 * time.Second
// Config — подключение к Jellyfin.
type Config struct {
URL string
APIKey string
Proxy string // опц. HTTP-прокси
Timeout time.Duration
}
// Client — клиент Jellyfin API.
type Client struct {
base string
apiKey string
hc *http.Client
log *slog.Logger
}
// New собирает клиент с опц. прокси. logger nil → slog.Default().
func New(cfg Config, logger *slog.Logger) (*Client, error) {
base, err := url.Parse(strings.TrimRight(cfg.URL, "/"))
if err != nil {
return nil, fmt.Errorf("jellyfin: parse url %q: %w", cfg.URL, err)
}
timeout := cfg.Timeout
if timeout <= 0 {
timeout = defaultTimeout
}
transport := http.DefaultTransport
if cfg.Proxy != "" {
pu, perr := url.Parse(cfg.Proxy)
if perr != nil {
return nil, fmt.Errorf("jellyfin: parse proxy %q: %w", cfg.Proxy, perr)
}
// Клонируем дефолтный транспорт (dial/TLS-таймауты, keep-alive), а не
// собираем голый — как в metadata-клиенте.
t := http.DefaultTransport.(*http.Transport).Clone()
t.Proxy = http.ProxyURL(pu)
transport = t
}
if logger == nil {
logger = slog.Default()
}
return &Client{
base: base.String(),
apiKey: cfg.APIKey,
hc: &http.Client{Timeout: timeout, Transport: transport},
log: logger,
}, nil
}
// RefreshLibraries запускает скан всех библиотек Jellyfin
// (POST /Library/Refresh). Скан инкрементальный — полный дёшев, поэтому
// точечный скан конкретной папки не делаем (сложнее, не в духе сервиса).
// Ответ при успехе — 204 No Content.
func (c *Client) RefreshLibraries(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.base+"/Library/Refresh", nil)
if err != nil {
return fmt.Errorf("jellyfin: build request: %w", err)
}
req.Header.Set("X-Emby-Token", c.apiKey)
start := time.Now()
resp, err := c.hc.Do(req)
if err != nil {
return fmt.Errorf("jellyfin: refresh: %w", err)
}
defer func() { _ = resp.Body.Close() }()
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<10))
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("jellyfin: refresh: status %d body %q",
resp.StatusCode, strings.TrimSpace(string(body)))
}
c.log.Info("jellyfin: library refresh triggered", "duration", time.Since(start))
return nil
}