Release v0.2.34

This commit is contained in:
ponzischeme89
2026-08-09 08:25:50 +12:00
parent b1128bcce2
commit fdd9e6cab2
116 changed files with 11418 additions and 879 deletions
+52
View File
@@ -373,6 +373,21 @@ func (c *Client) SetPlayed(ctx context.Context, cred Credentials, itemID string,
return c.userDataCall(ctx, method, path, cred)
}
// HideFromResume removes an item from resume and next-up feeds without marking it played.
func (c *Client) HideFromResume(ctx context.Context, cred Credentials, itemID string) (json.RawMessage, error) {
params := url.Values{"Hide": {"true"}}
path := "/Users/" + url.PathEscape(cred.UserID) + "/Items/" + url.PathEscape(itemID) + "/HideFromResume"
req, err := c.newRequest(ctx, http.MethodPost, path, params, cred, nil)
if err != nil {
return nil, err
}
var raw json.RawMessage
if err := c.do(req, &raw); err != nil {
return nil, err
}
return raw, nil
}
// RefreshItem asks Emby to re-scan one item's files.
//
// It exists for the subtitle download: Bazarr writes the new .srt beside the media file
@@ -501,6 +516,43 @@ func (c *Client) TrickplayBytes(
return io.ReadAll(io.LimitReader(resp.Body, to-from+1))
}
// MaxSubtitleBytes caps a subtitle read. A feature-length SubRip file is tens of
// kilobytes; a megabyte is far past anything genuine and is what an Emby that answered
// with the media file instead would send.
const MaxSubtitleBytes = 4 << 20
// SubtitleBytes reads a text subtitle track's content.
//
// This is the one place the gateway pulls a subtitle *out* of Emby rather than pointing
// the television at it, and it exists so a track can be used as a timing reference. SubRip
// is asked for because that is what the sync reads and writes; Emby converts from whatever
// the container holds.
func (c *Client) SubtitleBytes(
ctx context.Context, cred Credentials, itemID, mediaSourceID string, index int,
) ([]byte, error) {
if mediaSourceID == "" {
mediaSourceID = itemID
}
path := fmt.Sprintf(
"/Videos/%s/%s/Subtitles/%d/Stream.srt",
url.PathEscape(itemID), url.PathEscape(mediaSourceID), index,
)
req, err := c.newRequest(ctx, http.MethodGet, path, nil, cred, nil)
if err != nil {
return nil, err
}
resp, err := c.http.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))
return nil, &APIError{StatusCode: resp.StatusCode, Body: string(body)}
}
return io.ReadAll(io.LimitReader(resp.Body, MaxSubtitleBytes))
}
// StreamURL is the direct-play URL handed to the TV. It points at the *public* Emby
// address: video never flows through the gateway, only metadata does.
func (c *Client) StreamURL(cred Credentials, itemID string) string {