mirror of
https://github.com/hrfee/jfa-go.git
synced 2026-01-18 16:47:42 +01:00
jellyseerr: use in profiles, apply on user creation and modification
added in the same way as ombi profiles. Most code is copy-pasted and adjusted from ombi (especially on web), so maybe this can be merged in the future. Also, profile names are url-escaped like announcement template names were not too long ago. API client has "LogRequestBodies" option which just dumps the request body when enabled (useful for recreating reqs in the jellyseerr swagger UI). User.Name() helper returns a name from all three possible values in the struct.
This commit is contained in:
@@ -21,13 +21,14 @@ const (
|
||||
|
||||
// Jellyseerr represents a running Jellyseerr instance.
|
||||
type Jellyseerr struct {
|
||||
server, key string
|
||||
header map[string]string
|
||||
httpClient *http.Client
|
||||
userCache map[string]User // Map of jellyfin IDs to users
|
||||
cacheExpiry time.Time
|
||||
cacheLength time.Duration
|
||||
timeoutHandler common.TimeoutHandler
|
||||
server, key string
|
||||
header map[string]string
|
||||
httpClient *http.Client
|
||||
userCache map[string]User // Map of jellyfin IDs to users
|
||||
cacheExpiry time.Time
|
||||
cacheLength time.Duration
|
||||
timeoutHandler common.TimeoutHandler
|
||||
LogRequestBodies bool
|
||||
}
|
||||
|
||||
// NewJellyseerr returns an Ombi object.
|
||||
@@ -44,10 +45,11 @@ func NewJellyseerr(server, key string, timeoutHandler common.TimeoutHandler) *Je
|
||||
header: map[string]string{
|
||||
"X-Api-Key": key,
|
||||
},
|
||||
cacheLength: time.Duration(30) * time.Minute,
|
||||
cacheExpiry: time.Now(),
|
||||
timeoutHandler: timeoutHandler,
|
||||
userCache: map[string]User{},
|
||||
cacheLength: time.Duration(30) * time.Minute,
|
||||
cacheExpiry: time.Now(),
|
||||
timeoutHandler: timeoutHandler,
|
||||
userCache: map[string]User{},
|
||||
LogRequestBodies: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +61,9 @@ func (js *Jellyseerr) getJSON(url string, params map[string]string, queryParams
|
||||
var req *http.Request
|
||||
if params != nil {
|
||||
jsonParams, _ := json.Marshal(params)
|
||||
if js.LogRequestBodies {
|
||||
fmt.Printf("Jellyseerr API Client: Sending Data \"%s\"\n", string(jsonParams))
|
||||
}
|
||||
req, _ = http.NewRequest("GET", url+"?"+queryParams.Encode(), bytes.NewBuffer(jsonParams))
|
||||
} else {
|
||||
req, _ = http.NewRequest("GET", url+"?"+queryParams.Encode(), nil)
|
||||
@@ -94,6 +99,9 @@ func (js *Jellyseerr) getJSON(url string, params map[string]string, queryParams
|
||||
func (js *Jellyseerr) send(mode string, url string, data any, response bool, headers map[string]string) (string, int, error) {
|
||||
responseText := ""
|
||||
params, _ := json.Marshal(data)
|
||||
if js.LogRequestBodies {
|
||||
fmt.Printf("Jellyseerr API Client: Sending Data \"%s\"\n", string(params))
|
||||
}
|
||||
req, _ := http.NewRequest(mode, url, bytes.NewBuffer(params))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
for name, value := range js.header {
|
||||
@@ -291,7 +299,7 @@ func (js *Jellyseerr) ApplyTemplateToUser(jfID string, tmpl UserTemplate) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (js *Jellyseerr) ModifyUser(jfID string, conf map[UserField]string) error {
|
||||
func (js *Jellyseerr) ModifyUser(jfID string, conf map[UserField]any) error {
|
||||
u, err := js.MustGetUser(jfID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -327,13 +335,16 @@ func (js *Jellyseerr) DeleteUser(jfID string) error {
|
||||
}
|
||||
|
||||
func (js *Jellyseerr) GetNotificationPreferences(jfID string) (Notifications, error) {
|
||||
var data Notifications
|
||||
u, err := js.MustGetUser(jfID)
|
||||
if err != nil {
|
||||
return data, err
|
||||
return Notifications{}, err
|
||||
}
|
||||
return js.GetNotificationPreferencesByID(u.ID)
|
||||
}
|
||||
|
||||
resp, status, err := js.getJSON(fmt.Sprintf(js.server+"/user/%d/settings/notifications", u.ID), nil, url.Values{})
|
||||
func (js *Jellyseerr) GetNotificationPreferencesByID(jellyseerrID int64) (Notifications, error) {
|
||||
var data Notifications
|
||||
resp, status, err := js.getJSON(fmt.Sprintf(js.server+"/user/%d/settings/notifications", jellyseerrID), nil, url.Values{})
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
@@ -360,7 +371,7 @@ func (js *Jellyseerr) ApplyNotificationsTemplateToUser(jfID string, tmpl Notific
|
||||
return nil
|
||||
}
|
||||
|
||||
func (js *Jellyseerr) ModifyNotifications(jfID string, conf map[NotificationsField]string) error {
|
||||
func (js *Jellyseerr) ModifyNotifications(jfID string, conf map[NotificationsField]any) error {
|
||||
u, err := js.MustGetUser(jfID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -375,3 +386,21 @@ func (js *Jellyseerr) ModifyNotifications(jfID string, conf map[NotificationsFie
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (js *Jellyseerr) GetUsers() (map[string]User, error) {
|
||||
err := js.getUsers()
|
||||
return js.userCache, err
|
||||
}
|
||||
|
||||
func (js *Jellyseerr) UserByID(jellyseerrID int64) (User, error) {
|
||||
resp, status, err := js.getJSON(js.server+fmt.Sprintf("/user/%d", jellyseerrID), nil, url.Values{})
|
||||
var data User
|
||||
if status != 200 {
|
||||
return data, fmt.Errorf("failed (error %d)", status)
|
||||
}
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
err = json.Unmarshal([]byte(resp), &data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
@@ -11,61 +11,74 @@ const (
|
||||
|
||||
type User struct {
|
||||
UserTemplate // Note: You can set this with User.UserTemplate = value.
|
||||
Warnings []any `json:"warnings"`
|
||||
ID int `json:"id"`
|
||||
Email string `json:"email"`
|
||||
PlexUsername string `json:"plexUsername"`
|
||||
JellyfinUsername string `json:"jellyfinUsername"`
|
||||
Username string `json:"username"`
|
||||
RecoveryLinkExpirationDate any `json:"recoveryLinkExpirationDate"`
|
||||
PlexID string `json:"plexId"`
|
||||
JellyfinUserID string `json:"jellyfinUserId"`
|
||||
JellyfinDeviceID string `json:"jellyfinDeviceId"`
|
||||
JellyfinAuthToken string `json:"jellyfinAuthToken"`
|
||||
PlexToken string `json:"plexToken"`
|
||||
Avatar string `json:"avatar"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
RequestCount int `json:"requestCount"`
|
||||
DisplayName string `json:"displayName"`
|
||||
UserType int64 `json:"userType,omitempty"`
|
||||
Warnings []any `json:"warnings,omitempty"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
PlexUsername string `json:"plexUsername,omitempty"`
|
||||
JellyfinUsername string `json:"jellyfinUsername,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
RecoveryLinkExpirationDate any `json:"recoveryLinkExpirationDate,omitempty"`
|
||||
PlexID string `json:"plexId,omitempty"`
|
||||
JellyfinUserID string `json:"jellyfinUserId,omitempty"`
|
||||
JellyfinDeviceID string `json:"jellyfinDeviceId,omitempty"`
|
||||
JellyfinAuthToken string `json:"jellyfinAuthToken,omitempty"`
|
||||
PlexToken string `json:"plexToken,omitempty"`
|
||||
Avatar string `json:"avatar,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty"`
|
||||
RequestCount int64 `json:"requestCount,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
}
|
||||
|
||||
func (u User) Name() string {
|
||||
var n string
|
||||
if u.Username != "" {
|
||||
n = u.Username
|
||||
} else if u.JellyfinUsername != "" {
|
||||
n = u.JellyfinUsername
|
||||
}
|
||||
if u.DisplayName != "" {
|
||||
n += " (" + u.DisplayName + ")"
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type UserTemplate struct {
|
||||
Permissions Permissions `json:"permissions"`
|
||||
UserType int `json:"userType"`
|
||||
MovieQuotaLimit any `json:"movieQuotaLimit"`
|
||||
MovieQuotaDays any `json:"movieQuotaDays"`
|
||||
TvQuotaLimit any `json:"tvQuotaLimit"`
|
||||
TvQuotaDays any `json:"tvQuotaDays"`
|
||||
Permissions Permissions `json:"permissions,omitempty"`
|
||||
MovieQuotaLimit any `json:"movieQuotaLimit,omitempty"`
|
||||
MovieQuotaDays any `json:"movieQuotaDays,omitempty"`
|
||||
TvQuotaLimit any `json:"tvQuotaLimit,omitempty"`
|
||||
TvQuotaDays any `json:"tvQuotaDays,omitempty"`
|
||||
}
|
||||
|
||||
type PageInfo struct {
|
||||
Pages int `json:"pages"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Results int `json:"results"`
|
||||
Page int `json:"page"`
|
||||
Pages int `json:"pages,omitempty"`
|
||||
PageSize int `json:"pageSize,omitempty"`
|
||||
Results int `json:"results,omitempty"`
|
||||
Page int `json:"page,omitempty"`
|
||||
}
|
||||
|
||||
type GetUsersDTO struct {
|
||||
Page PageInfo `json:"pageInfo"`
|
||||
Results []User `json:"results"`
|
||||
Page PageInfo `json:"pageInfo,omitempty"`
|
||||
Results []User `json:"results,omitempty"`
|
||||
}
|
||||
|
||||
type permissionsDTO struct {
|
||||
Permissions Permissions `json:"permissions"`
|
||||
Permissions Permissions `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
type Permissions int
|
||||
|
||||
type NotificationTypes struct {
|
||||
Discord int `json:"discord"`
|
||||
Email int `json:"email"`
|
||||
Pushbullet int `json:"pushbullet"`
|
||||
Pushover int `json:"pushover"`
|
||||
Slack int `json:"slack"`
|
||||
Telegram int `json:"telegram"`
|
||||
Webhook int `json:"webhook"`
|
||||
Webpush int `json:"webpush"`
|
||||
Discord int64 `json:"discord,omitempty"`
|
||||
Email int64 `json:"email,omitempty"`
|
||||
Pushbullet int64 `json:"pushbullet,omitempty"`
|
||||
Pushover int64 `json:"pushover,omitempty"`
|
||||
Slack int64 `json:"slack,omitempty"`
|
||||
Telegram int64 `json:"telegram,omitempty"`
|
||||
Webhook int64 `json:"webhook,omitempty"`
|
||||
Webpush int64 `json:"webpush,omitempty"`
|
||||
}
|
||||
|
||||
type NotificationsField string
|
||||
@@ -80,21 +93,21 @@ const (
|
||||
|
||||
type Notifications struct {
|
||||
NotificationsTemplate
|
||||
PgpKey any `json:"pgpKey"`
|
||||
DiscordID string `json:"discordId"`
|
||||
PushbulletAccessToken any `json:"pushbulletAccessToken"`
|
||||
PushoverApplicationToken any `json:"pushoverApplicationToken"`
|
||||
PushoverUserKey any `json:"pushoverUserKey"`
|
||||
TelegramChatID string `json:"telegramChatId"`
|
||||
PgpKey any `json:"pgpKey,omitempty"`
|
||||
DiscordID string `json:"discordId,omitempty"`
|
||||
PushbulletAccessToken any `json:"pushbulletAccessToken,omitempty"`
|
||||
PushoverApplicationToken any `json:"pushoverApplicationToken,omitempty"`
|
||||
PushoverUserKey any `json:"pushoverUserKey,omitempty"`
|
||||
TelegramChatID string `json:"telegramChatId,omitempty"`
|
||||
}
|
||||
|
||||
type NotificationsTemplate struct {
|
||||
EmailEnabled bool `json:"emailEnabled"`
|
||||
DiscordEnabled bool `json:"discordEnabled"`
|
||||
DiscordEnabledTypes int `json:"discordEnabledTypes"`
|
||||
PushoverSound any `json:"pushoverSound"`
|
||||
TelegramEnabled bool `json:"telegramEnabled"`
|
||||
TelegramSendSilently any `json:"telegramSendSilently"`
|
||||
WebPushEnabled bool `json:"webPushEnabled"`
|
||||
NotifTypes NotificationTypes `json:"notificationTypes"`
|
||||
EmailEnabled bool `json:"emailEnabled,omitempty"`
|
||||
DiscordEnabled bool `json:"discordEnabled,omitempty"`
|
||||
DiscordEnabledTypes int64 `json:"discordEnabledTypes,omitempty"`
|
||||
PushoverSound any `json:"pushoverSound,omitempty"`
|
||||
TelegramEnabled bool `json:"telegramEnabled,omitempty"`
|
||||
TelegramSendSilently any `json:"telegramSendSilently,omitempty"`
|
||||
WebPushEnabled bool `json:"webPushEnabled,omitempty"`
|
||||
NotifTypes NotificationTypes `json:"notificationTypes,omitempty"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user