Get/set/delete trusted users. Tweak friends list struct
Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
parent
12e801f83c
commit
6ffcf70090
5 changed files with 227 additions and 63 deletions
153
account.go
153
account.go
|
@ -2,9 +2,8 @@ package geddit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccountService handles communication with the account
|
// AccountService handles communication with the account
|
||||||
|
@ -28,9 +27,10 @@ type SubredditKarma struct {
|
||||||
// Settings are the user's account settings.
|
// Settings are the user's account settings.
|
||||||
// Some of the fields' descriptions are taken from:
|
// Some of the fields' descriptions are taken from:
|
||||||
// https://praw.readthedocs.io/en/latest/code_overview/other/preferences.html#praw.models.Preferences.update
|
// https://praw.readthedocs.io/en/latest/code_overview/other/preferences.html#praw.models.Preferences.update
|
||||||
// todo: these should probably be pointers with omitempty
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
// Control whose private messages you see: "everyone" or "whitelisted".
|
// Control whose private messages you see.
|
||||||
|
// - "everyone": everyone except blocked users
|
||||||
|
// - "whitelisted": only trusted users
|
||||||
AcceptPrivateMessages *string `json:"accept_pms,omitempty"`
|
AcceptPrivateMessages *string `json:"accept_pms,omitempty"`
|
||||||
// Allow Reddit to use your activity on Reddit to show you more relevant advertisements.
|
// Allow Reddit to use your activity on Reddit to show you more relevant advertisements.
|
||||||
ActivityRelevantAds *bool `json:"activity_relevant_ads,omitempty"`
|
ActivityRelevantAds *bool `json:"activity_relevant_ads,omitempty"`
|
||||||
|
@ -209,6 +209,13 @@ type Settings struct {
|
||||||
EnableVideoAutoplay *bool `json:"video_autoplay,omitempty"`
|
EnableVideoAutoplay *bool `json:"video_autoplay,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type rootRelationshipList struct {
|
||||||
|
Kind string `json:"kind,omitempty"`
|
||||||
|
Data struct {
|
||||||
|
Relationships []Relationship `json:"children"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
// Info returns some general information about your account.
|
// Info returns some general information about your account.
|
||||||
func (s *AccountService) Info(ctx context.Context) (*User, *Response, error) {
|
func (s *AccountService) Info(ctx context.Context) (*User, *Response, error) {
|
||||||
path := "api/v1/me"
|
path := "api/v1/me"
|
||||||
|
@ -296,6 +303,7 @@ func (s *AccountService) Trophies(ctx context.Context) ([]Trophy, *Response, err
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: use Things struct
|
||||||
var trophies []Trophy
|
var trophies []Trophy
|
||||||
for _, trophy := range root.Data.Trophies {
|
for _, trophy := range root.Data.Trophies {
|
||||||
trophies = append(trophies, trophy.Data)
|
trophies = append(trophies, trophy.Data)
|
||||||
|
@ -304,52 +312,6 @@ func (s *AccountService) Trophies(ctx context.Context) ([]Trophy, *Response, err
|
||||||
return trophies, resp, nil
|
return trophies, resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type rootFriendList struct {
|
|
||||||
Friends []Relationship
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
|
||||||
func (l *rootFriendList) UnmarshalJSON(b []byte) error {
|
|
||||||
var resBody []interface{}
|
|
||||||
err := json.Unmarshal(b, &resBody)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(resBody) == 0 {
|
|
||||||
return errors.New("unexpected data length received")
|
|
||||||
}
|
|
||||||
|
|
||||||
data, ok := resBody[0].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return errors.New("unexpected data type received")
|
|
||||||
}
|
|
||||||
|
|
||||||
dataMap, ok := data["data"].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return errors.New("data does not contain expected field")
|
|
||||||
}
|
|
||||||
|
|
||||||
children, ok := dataMap["children"].([]interface{})
|
|
||||||
if !ok {
|
|
||||||
return errors.New("data does not contain expected field")
|
|
||||||
}
|
|
||||||
|
|
||||||
byteValue, err := json.Marshal(children)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var friends []Relationship
|
|
||||||
err = json.Unmarshal(byteValue, &friends)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Friends = friends
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Friends returns a list of your friends.
|
// Friends returns a list of your friends.
|
||||||
func (s *AccountService) Friends(ctx context.Context) ([]Relationship, *Response, error) {
|
func (s *AccountService) Friends(ctx context.Context) ([]Relationship, *Response, error) {
|
||||||
path := "prefs/friends"
|
path := "prefs/friends"
|
||||||
|
@ -359,20 +321,13 @@ func (s *AccountService) Friends(ctx context.Context) ([]Relationship, *Response
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(rootFriendList)
|
root := make([]rootRelationshipList, 2)
|
||||||
resp, err := s.client.Do(ctx, req, root)
|
resp, err := s.client.Do(ctx, req, &root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return root.Friends, resp, nil
|
return root[0].Data.Relationships, resp, nil
|
||||||
}
|
|
||||||
|
|
||||||
type rootBlockedListing struct {
|
|
||||||
Kind string `json:"kind,omitempty"`
|
|
||||||
Data struct {
|
|
||||||
Blocked []Relationship `json:"children"`
|
|
||||||
} `json:"data"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocked returns a list of your blocked users.
|
// Blocked returns a list of your blocked users.
|
||||||
|
@ -384,11 +339,85 @@ func (s *AccountService) Blocked(ctx context.Context) ([]Relationship, *Response
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(rootBlockedListing)
|
root := new(rootRelationshipList)
|
||||||
resp, err := s.client.Do(ctx, req, root)
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return root.Data.Blocked, resp, nil
|
return root.Data.Relationships, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Messaging returns blocked users and trusted users, respectively.
|
||||||
|
func (s *AccountService) Messaging(ctx context.Context) ([]Relationship, []Relationship, *Response, error) {
|
||||||
|
path := "prefs/messaging"
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := make([]rootRelationshipList, 2)
|
||||||
|
resp, err := s.client.Do(ctx, req, &root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
blocked := root[0].Data.Relationships
|
||||||
|
trusted := root[1].Data.Relationships
|
||||||
|
|
||||||
|
return blocked, trusted, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trusted returns a list of your trusted users.
|
||||||
|
func (s *AccountService) Trusted(ctx context.Context) ([]Relationship, *Response, error) {
|
||||||
|
path := "prefs/trusted"
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := new(rootRelationshipList)
|
||||||
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.Data.Relationships, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTrusted adds a user to your trusted users.
|
||||||
|
// This is not visible in the Reddit API docs.
|
||||||
|
func (s *AccountService) AddTrusted(ctx context.Context, username string) (*Response, error) {
|
||||||
|
path := "api/add_whitelisted"
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("api_type", "json")
|
||||||
|
form.Set("name", username)
|
||||||
|
// todo: you can also do this with the user id. form.Set("id", id). should we? or is this enough?
|
||||||
|
|
||||||
|
req, err := s.client.NewPostForm(path, form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(ctx, req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTrusted removes a user from your trusted users.
|
||||||
|
// This is not visible in the Reddit API docs.
|
||||||
|
func (s *AccountService) RemoveTrusted(ctx context.Context, username string) (*Response, error) {
|
||||||
|
path := "api/remove_whitelisted"
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("name", username)
|
||||||
|
// todo: you can also do this with the user id. form.Set("id", id). should we? or is this enough?
|
||||||
|
|
||||||
|
req, err := s.client.NewPostForm(path, form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.Do(ctx, req, nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -112,6 +113,15 @@ var expectedRelationships = []Relationship{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expectedRelationships2 = []Relationship{
|
||||||
|
{
|
||||||
|
ID: "r9_1re60i",
|
||||||
|
User: "test3",
|
||||||
|
UserID: "t2_test3",
|
||||||
|
Created: &Timestamp{time.Date(2020, 3, 6, 2, 27, 0, 0, time.UTC)},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccountService_Info(t *testing.T) {
|
func TestAccountService_Info(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
@ -230,3 +240,75 @@ func TestAccountService_Blocked(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedRelationships, relationships)
|
assert.Equal(t, expectedRelationships, relationships)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccountService_Messaging(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/account/messaging.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/prefs/messaging", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
blocked, trusted, _, err := client.Account.Messaging(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedRelationships, blocked)
|
||||||
|
assert.Equal(t, expectedRelationships2, trusted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountService_Trusted(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/account/trusted.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/prefs/trusted", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
relationships, _, err := client.Account.Trusted(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedRelationships, relationships)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountService_AddTrusted(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/add_whitelisted", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("api_type", "json")
|
||||||
|
form.Set("name", "test123")
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, form, r.Form)
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := client.Account.AddTrusted(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountService_RemoveTrusted(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/remove_whitelisted", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("name", "test123")
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, form, r.Form)
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := client.Account.RemoveTrusted(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ type RedditError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *RedditError) Error() string {
|
func (e *RedditError) Error() string {
|
||||||
return fmt.Sprintf("%s: %s because of field %q", e.Label, e.Reason, e.Field)
|
return fmt.Sprintf("field %q caused %s: %s", e.Field, e.Label, e.Reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
|
34
testdata/account/messaging.json
vendored
Normal file
34
testdata/account/messaging.json
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"kind": "UserList",
|
||||||
|
"data": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"date": 1593362635,
|
||||||
|
"rel_id": "r9_1r4879",
|
||||||
|
"name": "test1",
|
||||||
|
"id": "t2_test1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": 1593362642,
|
||||||
|
"rel_id": "r9_1re930",
|
||||||
|
"name": "test2",
|
||||||
|
"id": "t2_test2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "UserList",
|
||||||
|
"data": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"date": 1583461620,
|
||||||
|
"rel_id": "r9_1re60i",
|
||||||
|
"name": "test3",
|
||||||
|
"id": "t2_test3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
19
testdata/account/trusted.json
vendored
Normal file
19
testdata/account/trusted.json
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"kind": "UserList",
|
||||||
|
"data": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"date": 1593362635,
|
||||||
|
"rel_id": "r9_1r4879",
|
||||||
|
"name": "test1",
|
||||||
|
"id": "t2_test1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": 1593362642,
|
||||||
|
"rel_id": "r9_1re930",
|
||||||
|
"name": "test2",
|
||||||
|
"id": "t2_test2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue