1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 00:50:12 +00:00

jellyseerr: add user modification methods

addded permissions get/set before realizing it already comes as part of
the User object. Split User attributes that will be templated into
UserTemplate struct, which User inherits. ApplyTemplateToUser takes a
UserTemplate, while ModifyUser takes a plain map with some typed fields
(display name and email, for now).
This commit is contained in:
Harvey Tindall 2024-07-29 17:26:14 +01:00
parent 9c34192b4f
commit 73e985c45c
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
3 changed files with 137 additions and 11 deletions

View File

@ -91,7 +91,7 @@ func (js *Jellyseerr) getJSON(url string, params map[string]string, queryParams
}
// does a POST and optionally returns response as string. Returns a string instead of an io.reader bcs i couldn't get it working otherwise.
func (js *Jellyseerr) send(mode string, url string, data interface{}, response bool, headers map[string]string) (string, int, error) {
func (js *Jellyseerr) send(mode string, url string, data any, response bool, headers map[string]string) (string, int, error) {
responseText := ""
params, _ := json.Marshal(data)
req, _ := http.NewRequest(mode, url, bytes.NewBuffer(params))
@ -129,11 +129,11 @@ func (js *Jellyseerr) send(mode string, url string, data interface{}, response b
return responseText, resp.StatusCode, nil
}
func (js *Jellyseerr) post(url string, data map[string]interface{}, response bool) (string, int, error) {
func (js *Jellyseerr) post(url string, data any, response bool) (string, int, error) {
return js.send("POST", url, data, response, nil)
}
func (js *Jellyseerr) put(url string, data map[string]interface{}, response bool) (string, int, error) {
func (js *Jellyseerr) put(url string, data any, response bool) (string, int, error) {
return js.send("PUT", url, data, response, nil)
}
@ -236,3 +236,92 @@ func (js *Jellyseerr) Me() (User, error) {
err = json.Unmarshal([]byte(resp), &data)
return data, err
}
func (js *Jellyseerr) GetPermissions(jfID string) (Permissions, error) {
data := permissionsDTO{Permissions: -1}
u, err := js.MustGetUser(jfID)
if err != nil {
return data.Permissions, err
}
resp, status, err := js.getJSON(fmt.Sprintf(js.server+"/user/%d/settings/permissions", u.ID), nil, url.Values{})
if err != nil {
return data.Permissions, err
}
if status != 200 {
return data.Permissions, fmt.Errorf("failed (error %d)", status)
}
err = json.Unmarshal([]byte(resp), &data)
return data.Permissions, err
}
func (js *Jellyseerr) SetPermissions(jfID string, perm Permissions) error {
u, err := js.MustGetUser(jfID)
if err != nil {
return err
}
_, status, err := js.post(fmt.Sprintf(js.server+"/user/%d/settings/permissions", u.ID), permissionsDTO{Permissions: perm}, false)
if err != nil {
return err
}
if status != 200 && status != 201 {
return fmt.Errorf("failed (error %d)", status)
}
u.Permissions = perm
js.userCache[jfID] = u
return nil
}
func (js *Jellyseerr) ApplyTemplateToUser(jfID string, tmpl UserTemplate) error {
u, err := js.MustGetUser(jfID)
if err != nil {
return err
}
_, status, err := js.put(fmt.Sprintf(js.server+"/user/%d", u.ID), tmpl, false)
if err != nil {
return err
}
if status != 200 && status != 201 {
return fmt.Errorf("failed (error %d)", status)
}
u.UserTemplate = tmpl
js.userCache[jfID] = u
return nil
}
func (js *Jellyseerr) ModifyUser(jfID string, conf map[UserField]string) error {
u, err := js.MustGetUser(jfID)
if err != nil {
return err
}
_, status, err := js.put(fmt.Sprintf(js.server+"/user/%d", u.ID), conf, false)
if err != nil {
return err
}
if status != 200 && status != 201 {
return fmt.Errorf("failed (error %d)", status)
}
// Lazily just invalidate the cache.
js.cacheExpiry = time.Now()
return nil
}
func (js *Jellyseerr) DeleteUser(jfID string) error {
u, err := js.MustGetUser(jfID)
if err != nil {
return err
}
_, status, err := js.send("DELETE", fmt.Sprintf(js.server+"/user/%d", u.ID), nil, false, nil)
if status != 200 && status != 201 {
return fmt.Errorf("failed (error %d)", status)
}
if err != nil {
return err
}
delete(js.userCache, jfID)
return err
}

View File

@ -9,6 +9,7 @@ import (
const (
API_KEY = "MTcyMjI2MDM2MTYyMzMxNDZkZmYyLTE4MzMtNDUyNy1hODJlLTI0MTZkZGUyMDg2Ng=="
URI = "http://localhost:5055"
PERM = 2097184
)
func client() *Jellyseerr {
@ -26,7 +27,7 @@ func TestMe(t *testing.T) {
}
}
func TestImportFromJellyfin(t *testing.T) {
/* func TestImportFromJellyfin(t *testing.T) {
js := client()
list, err := js.ImportFromJellyfin("6b75e189efb744f583aa2e8e9cee41d3")
if err != nil {
@ -35,7 +36,7 @@ func TestImportFromJellyfin(t *testing.T) {
if len(list) == 0 {
t.Fatalf("returned no users")
}
}
} */
func TestMustGetUser(t *testing.T) {
js := client()
@ -47,3 +48,22 @@ func TestMustGetUser(t *testing.T) {
t.Fatalf("returned no users")
}
}
func TestSetPermissions(t *testing.T) {
js := client()
err := js.SetPermissions("6b75e189efb744f583aa2e8e9cee41d3", PERM)
if err != nil {
t.Fatalf("returned error %+v", err)
}
}
func TestGetPermissions(t *testing.T) {
js := client()
perm, err := js.GetPermissions("6b75e189efb744f583aa2e8e9cee41d3")
if err != nil {
t.Fatalf("returned error %+v", err)
}
if perm != PERM {
t.Fatalf("got unexpected perm code %d", perm)
}
}

View File

@ -2,8 +2,15 @@ package jellyseerr
import "time"
type UserField string
const (
FieldDisplayName UserField = "displayName"
FieldEmail UserField = "email"
)
type User struct {
Permissions int `json:"permissions"`
UserTemplate // Note: You can set this with User.UserTemplate = value.
Warnings []any `json:"warnings"`
ID int `json:"id"`
Email string `json:"email"`
@ -11,23 +18,27 @@ type User struct {
JellyfinUsername string `json:"jellyfinUsername"`
Username string `json:"username"`
RecoveryLinkExpirationDate any `json:"recoveryLinkExpirationDate"`
UserType int `json:"userType"`
PlexID string `json:"plexId"`
JellyfinUserID string `json:"jellyfinUserId"`
JellyfinDeviceID string `json:"jellyfinDeviceId"`
JellyfinAuthToken string `json:"jellyfinAuthToken"`
PlexToken string `json:"plexToken"`
Avatar string `json:"avatar"`
MovieQuotaLimit any `json:"movieQuotaLimit"`
MovieQuotaDays any `json:"movieQuotaDays"`
TvQuotaLimit any `json:"tvQuotaLimit"`
TvQuotaDays any `json:"tvQuotaDays"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
RequestCount int `json:"requestCount"`
DisplayName string `json:"displayName"`
}
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"`
}
type PageInfo struct {
Pages int `json:"pages"`
PageSize int `json:"pageSize"`
@ -39,3 +50,9 @@ type GetUsersDTO struct {
Page PageInfo `json:"pageInfo"`
Results []User `json:"results"`
}
type permissionsDTO struct {
Permissions Permissions `json:"permissions"`
}
type Permissions int