66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
// backend/internal/jellyfin.go
|
|
package internal
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// Minimal Jellyfin client
|
|
|
|
type jfAuthResult struct {
|
|
AccessToken string `json:"AccessToken"`
|
|
User struct {
|
|
Id string `json:"Id"`
|
|
Name string `json:"Name"`
|
|
} `json:"User"`
|
|
}
|
|
|
|
type Jellyfin struct {
|
|
BaseURL string
|
|
Client *http.Client
|
|
}
|
|
|
|
func NewJellyfin() *Jellyfin {
|
|
return &Jellyfin{
|
|
BaseURL: os.Getenv("JELLYFIN_URL"),
|
|
Client: &http.Client{Timeout: 10 * time.Second},
|
|
}
|
|
}
|
|
|
|
// Authenticate against /Users/AuthenticateByName using Pw (plaintext)
|
|
func (j *Jellyfin) AuthenticateByName(username, password string) (jfAuthResult, error) {
|
|
var out jfAuthResult
|
|
body := map[string]string{"Username": username, "Pw": password}
|
|
b, _ := json.Marshal(body)
|
|
|
|
req, _ := http.NewRequest("POST", j.BaseURL+"/Users/AuthenticateByName", bytes.NewReader(b))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
// Jellyfin client descriptor (no token yet)
|
|
req.Header.Set("Authorization",
|
|
`MediaBrowser Client="Pegasus", Device="Pegasus Web", DeviceId="pegasus-web", Version="1.0.0"`)
|
|
|
|
resp, err := j.Client.Do(req)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
|
return out, fmt.Errorf("login failed: %s", resp.Status)
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
|
|
return out, err
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (j *Jellyfin) RefreshLibrary(token string) {
|
|
req, _ := http.NewRequest("GET", j.BaseURL+"/Library/Refresh", nil)
|
|
req.Header.Set("X-MediaBrowser-Token", token)
|
|
_, _ = j.Client.Do(req)
|
|
}
|