grim/paytreon

b542428d4fe6
Parents 8b3c6c709f2b
Children
Move the package to the new import path and other changes from who knows when
  • +3 -1
    go.mod
  • +0 -228
    types.go
  • +0 -140
    types_test.go
  • +126 -0
    v1/types.go
  • +140 -0
    v1/types_test.go
  • +228 -0
    v2/types.go
  • --- a/go.mod Wed Apr 10 02:44:56 2019 -0500
    +++ b/go.mod Mon Apr 27 21:48:18 2020 -0500
    @@ -1,4 +1,6 @@
    -module bitbucket.org/rw_grim/paytreon
    +module keep.imfreedom.org/grim/paytreon
    +
    +go 1.14
    require (
    github.com/google/jsonapi v0.0.0-20181016150055-d0428f63eb51
    --- a/types.go Wed Apr 10 02:44:56 2019 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,228 +0,0 @@
    -package paytreon
    -
    -import (
    - "encoding/json"
    -)
    -
    -type Address struct {
    - ID string `jsonapi:"primary,address"`
    -
    - Addressee string `jsonapi:"attr,addressee"`
    - Line1 string `jsonapi:"attr,line_1"`
    - Line2 string `jsonapi:"attr,line_2"`
    - PostalCode string `jsonapi:"attr,postal_code"`
    - City string `jsonapi:"attr,city"`
    - State string `jsonapi:"attr,state"`
    - Country string `jsonapi:"attr,country"`
    - PhoneNumber string `jsonapi:"attr,phone_number"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    -
    - User *User `jsonapi:"relation,user,omitempty"`
    - Campaigns []*Campaign `jsonapi:"relation,campaigns,omitempty"`
    -}
    -
    -type Benefit struct {
    - ID string `jsonapi:"attr,primary,benefit"`
    - Title string `jsonapi:"attr,title"`
    - Description string `jsonapi:"attr,description"`
    - BenefitType string `jsonapi:"attr,benefit_type"`
    - RuleType string `jsonapi:"attr,rule_type"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    - DeliveredDeliverablesCount int `jsonapi:"attr,delivered_deliverables_count"`
    - NotDeliveredDeliverablesCount int `jsonapi:"attr,not_delivered_deliverables_count"`
    - DeliverablesDueTodayCount int `jsonapi:"attr,deliverables_due_today_count"`
    - NextDeliverableDueDate string `jsonapi:"attr,next_deliverable_due_date"`
    - TiersCount int `jsonapi:"attr,tiers_count"`
    - IsDeleted bool `jsonapi:"attr,is_deleted"`
    - IsPublished bool `jsonapi:"attr,is_published"`
    - AppExternalID string `jsonapi:"attr,app_external_id"`
    - AppMeta *json.RawMessage `jsonapi:"attr,app_meta"`
    -
    - Tiers []*Tier `jsonapi:"relation,tiers,omitempty"`
    - Deliverables []*Deliverable `jsonapi:"relation,deliverables,omitempty"`
    - Campaign *Campaign `jsonapi:"relation,compaign,omitempty"`
    - // CampaignInstallation *CampaignInstallation `jsonapi:"relation,campaign_installation"`
    -}
    -
    -type Campaign struct {
    - ID string `jsonapi:"primary,campaign"`
    -
    - Summary string `jsonapi:"attr,summary"`
    - CreationName string `jsonapi:"attr,creation_name"`
    - PayPerName string `jsonapi:"attr,pay_per_name"`
    - OneLiner string `jsonapi:"attr,one_liner"`
    - MainVideoEmbed string `jsonapi:"attr,main_video_embed"`
    - MainVideoURL string `jsonapi:"attr,main_video_url"`
    - ImageURL string `jsonapi:"attr,image_url"`
    - ImageSmallURL string `jsonapi:"attr,image_small_url"`
    - ThanksVideoURL string `jsonapi:"attr,thanks_video_url"`
    - ThanksEmbed string `jsonapi:"attr,thanks_embed"`
    - ThanksMsg string `jsonapi:"attr,thanks_msg"`
    - IsMonthly bool `jsonapi:"attr,is_monthly"`
    - HasRss bool `jsonapi:"attr,has_rss"`
    - HasSentRssNotify bool `jsonapi:"attr,has_sent_rss_notify"`
    - RssFeedTitle string `jsonapi:"attr,rss_feed_title"`
    - RssArtworkURL string `jsonapi:"attr,rss_artwork_url"`
    - IsNsfw bool `jsonapi:"attr,is_nsfw"`
    - IsChargedImmediately bool `jsonapi:"attr,is_charged_immediately"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    - PublishedAt string `jsonapi:"attr,published_at"`
    - PledgeURL string `jsonapi:"attr,pledge_url"`
    - PatronCount int `jsonapi:"attr,patron_count"`
    - DiscordServerID string `jsonapi:"attr,discord_service_id"`
    - GoogleAnalyticsID string `jsonapi:"attr,google_analytics_id"`
    - EarningsVisibility string `jsonapi:"attr,earnings_visibility"`
    -
    - Tiers []*Tier `jsonapi:"relation,tiers,omitempty"`
    - Creator *User `jsonapi:"relation,creator,omitempty"`
    - Benefits []*Benefit `jsonapi:"relation,benefits,omitempty"`
    - Goals []*Goal `jsonapi:"relation,goals,omitempty"`
    -}
    -
    -type Deliverable struct {
    - ID string `jsonapi:"primary,deliverable"`
    -
    - CompletedAt string `jsonapi:"attr,completed_at"`
    - DeliveryStatus string `jsonapi:"attr,delivery_status"`
    - DueAt string `jsonapi:"attr,due_at"`
    -
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    - Benefit *Benefit `jsonapi:"relation,benefit,omitempty"`
    - Member *Member `jsonapi:"relation,member,omitempty"`
    - User *User `jsonapi:"relation,user,omitempty"`
    -}
    -
    -type Goal struct {
    - ID string `jsonapi:"primary,goal"`
    -
    - AmountCents int `jsonapi:"attr,amount_cents"`
    - Title string `jsonapi:"attr,title"`
    - Description string `jsonapi:"attr,description"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    - ReachedAt string `jsonapi:"attr,reached_at"`
    - CompletedPercentage int `jsonapi:"attr,completed_percentage"`
    -
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    -}
    -
    -type Media struct {
    - ID string `jsonapi:"primary,media"`
    -
    - Filename string `jsonapi:"attr,file_name"`
    - SizeBytes int `jsonapi:"attr,size_bytes"`
    - MimeType string `jsonapi:"attr,mimetype"`
    - State string `jsonapi:"attr,state"`
    - OwnerType string `jsonapi:"attr,owner_type"`
    - OwnerID string `jsonapi:"attr,owner_id"`
    - OwnerRelationship string `jsonapi:"attr,owner_relationship"`
    - UploadExpiresAt string `jsonapi:"attr,upload_expires_at"`
    - UploadURL string `jsonapi:"attr,upload_url"`
    - UploadParameters *json.RawMessage `jsonapi:"attr,upload_parameters"`
    - DownloadURL string `jsonapi:"attr,download_url"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    - Metadata *json.RawMessage `jsonapi:"attr,metadata"`
    -}
    -
    -type Member struct {
    - ID string `jsonapi:"primary,member"`
    -
    - PatronStatus string `jsonapi:"attr,patron_status"`
    - IsFollower bool `jsonapi:"attr,is_follower"`
    - FullName string `jsonapi:"attr,full_name"`
    - Email string `jsonapi:"attr,email"`
    - PledgeRelationshipStart string `jsonapi:"attr,pledge_relationship_start"`
    - LifetimeSupportCents int `jsonapi:"attr,lifetime_support_cents"`
    - CurrentlyEntitledAmountCents int `jsonapi:"attr,currently_entitled_amount_cents"`
    - LastChargeDate string `jsonapi:"attr,last_charge_date"`
    - LastChargeStatus string `jsonapi:"attr,last_charge_status"`
    - Note string `jsonapi:"attr,note"`
    - WillPayAmountCents int `jsonapi:"attr,will_pay_amount_cents"`
    -
    - Address *Address `jsonapi:"relation,address"`
    - Campaign *Campaign `jsonapi:"relation,campaign"`
    - CurrentlyEntitledTiers []*Tier `jsonapi:"relation,currently_entitled_tiers"`
    - User *User `jsonapi:"relation,user"`
    -}
    -
    -type OAuthClient struct {
    - ID string `jsonapi:"primary,oauthclient"`
    -
    - ClientSecret string `jsonapi:"attr,client_secret"`
    - Name string `jsonapi:"attr,name"`
    - Description string `jsonapi:"attr,description"`
    - AuthorName string `jsonapi:"attr,author_name"`
    - Domain string `jsonapi:"attr,domain"`
    - Version int `jsonapi:"attr,version"`
    - IconURL string `jsonapi:"attr,icon_url"`
    - PrivacyPolicyURL string `jsonapi:"attr,privacy_policy_url"`
    - TosURL string `jsonapi:"attr,tos_url"`
    - RedirectURIs string `jsonapi:"attr,redirect_uris"`
    - DefaultScopes string `jsonapi:"attr,default_scopes"`
    -
    - User *User `jsonapi:"relation,user,omitempty"`
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    - CreatorToken string `jsonapi:"relation,creator_token,omitempty"`
    - Apps []*PlatformApp `jsonapi:"relation,apps,omitempty"`
    -}
    -
    -type Tier struct {
    - ID string `jsonapi:"primary,tier"`
    -
    - AmountCents int `jsonapi:"attr,amount_cents"`
    - UserLimit int `jsonapi:"attr,user_limit"`
    - Remaining int `jsonapi:"attr,remaining"`
    - Description string `jsonapi:"attr,description"`
    - RequiresShipping bool `jsonapi:"attr,requires_shipping"`
    - CreatedAt string `jsonapi:"attr,created_at"`
    - URL string `jsonapi:"attr,url"`
    - PatronCount int `jsonapi:"attr,patron_count"`
    - PostCount int `jsonapi:"attr,post_count"`
    - DiscordRoleIDs *json.RawMessage `jsonapi:"attr,discord_role_ids"`
    - Title string `jsonapi:"attr,title"`
    - ImageURL string `jsonapi:"attr,image_url"`
    - EditedAt string `jsonapi:"attr,edited_at"`
    - Published bool `jsonapi:"attr,published"`
    - PublishedAt string `jsonapi:"attr,published_at"`
    - UnpublishedAt string `jsonapi:"attr,unpublished_at"`
    -
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    - TierImage *Media `jsonapi:"relation,tier_image,omitempty"`
    - Benefits []*Benefit `jsonapi:"relation,benefits,omitempty"`
    -}
    -
    -type User struct {
    - ID string `jsonapi:"primary,user"`
    -
    - Email string `jsonapi:"attr,email"`
    - FirstName string `jsonapi:"attr,first_name"`
    - LastName string `jsonapi:"attr,last_name"`
    - FullName string `jsonapi:"attr,full_name"`
    - IsEmailVerified bool `jsonapi:"attr,is_email_verified"`
    - Vanity string `jsonapi:"attr,vanity"`
    - About string `jsonapi:"attr,about"`
    - ImageURL string `jsonapi:"attr,image_url"`
    - ThumbURL string `jsonapi:"attr,thumb_url"`
    - CanSeeNSFW bool `jsonapi:"attr,can_see_nsfw"`
    - Created string `jsonapi:"attr,created"`
    - URL string `jsonapi:"attr,url"`
    - LikeCount int `jsonapi:"attr,like_count"`
    - HidePledges bool `jsonapi:"attr,hide_pledges"`
    - SocialConnections *json.RawMessage `jsonapi:"attr,social_connections"`
    -
    - Memberships []*Member `jsonapi:"relation,memberships,omitempty"`
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    -}
    -
    -type Webhook struct {
    - ID string `jsonapi:"primary,webhook"`
    -
    - Triggers []string `jsonapi:"attr,triggers"`
    - URI string `jsonapi:"attr,uri"`
    - Paused bool `jsonapi:"attr,paused"`
    - LastAttemptedAt string `jsonapi:"attr,last_attempted_at"`
    - NumConsecutiveTimesFailed int `jsonapi:"attr,num_consecutive_times_failed"`
    - Secret string `jsonapi:"attr,secret"`
    -
    - Client *OAuthClient `jsonapi:"relation,client,omitempty"`
    - Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    -}
    --- a/types_test.go Wed Apr 10 02:44:56 2019 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,140 +0,0 @@
    -package paytreon
    -
    -import (
    - "reflect"
    - "strings"
    - "testing"
    -
    - "github.com/google/jsonapi"
    -)
    -
    -func TestAddressUnmarshal(t *testing.T) {
    - data := `{"data": {
    - "attributes": {
    - "addressee": "somebody",
    - "city": "somecity",
    - "country": "somecountry",
    - "line_1": "someline1",
    - "line_2": "someline2",
    - "phone_number": null,
    - "postal_code": "somepostalcode",
    - "state": "somestate"
    - },
    - "id": "someid",
    - "type": "address"
    -}}`
    -
    - exp := Address{
    - ID: "someid",
    - Addressee: "somebody",
    - City: "somecity",
    - Country: "somecountry",
    - Line1: "someline1",
    - Line2: "someline2",
    - PhoneNumber: "",
    - PostalCode: "somepostalcode",
    - State: "somestate",
    - }
    -
    - var address Address
    - err := jsonapi.UnmarshalPayload(strings.NewReader(data), &address)
    - if err != nil {
    - t.Errorf("unexpected error: %s", err)
    - }
    -
    - if !reflect.DeepEqual(address, exp) {
    - t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", address, exp)
    - }
    -}
    -
    -func TestRewardUnmarshal(t *testing.T) {
    - data := `{"data": {
    - "attributes": {
    - "amount": 100,
    - "amount_cents": 50,
    - "created_at": "2018-05-23T21:27:59.077755+00:00",
    - "deleted_at": null,
    - "edited_at": "2018-05-23T21:27:59.077755+00:00",
    - "description": "somedescription",
    - "image_url": "http://some.img",
    - "patron_count": 100,
    - "post_count": 50,
    - "published": true,
    - "published_at": "2018-05-23T21:27:59.077755+00:00",
    - "requires_shipping": true,
    - "title": "sometitle",
    - "unpublished_at": null,
    - "url": "http://some.reward"
    - },
    - "id": "someid",
    - "type": "reward"
    -}}`
    -
    - expDate := "2018-05-23T21:27:59.077755+00:00"
    -
    - exp := Reward{
    - ID: "someid",
    - Amount: 100,
    - AmountCents: 50,
    - CreatedAt: expDate,
    - EditedAt: expDate,
    - Description: "somedescription",
    - ImageURL: "http://some.img",
    - PatronCount: 100,
    - PostCount: 50,
    - Published: true,
    - PublishedAt: expDate,
    - RequiresShipping: true,
    - Title: "sometitle",
    - URL: "http://some.reward",
    - }
    -
    - var act Reward
    - err := jsonapi.UnmarshalPayload(strings.NewReader(data), &act)
    - if err != nil {
    - t.Errorf("unexpected error: %s", err)
    - }
    -
    - if !reflect.DeepEqual(act, exp) {
    - t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", act, exp)
    - }
    -}
    -
    -func TestGoalUnmarshal(t *testing.T) {
    - data := `{"data": {
    - "attributes": {
    - "amount": 100,
    - "amount_cents": 50,
    - "completed_percentage": 75,
    - "created_at": "2018-05-23T21:27:59.077755+00:00",
    - "reached_at": null,
    - "title": "sometitle",
    - "description": "somedescription"
    - },
    - "id": "someid",
    - "type": "goal"
    -}}`
    -
    - expDate := "2018-05-23T21:27:59.077755+00:00"
    -
    - exp := Goal{
    - ID: "someid",
    - Amount: 100,
    - AmountCents: 50,
    - CompletedPercentage: 75,
    - CreatedAt: expDate,
    - ReachedAt: "",
    - Title: "sometitle",
    - Description: "somedescription",
    - }
    -
    - var act Goal
    - err := jsonapi.UnmarshalPayload(strings.NewReader(data), &act)
    - if err != nil {
    - t.Errorf("unexpected error: %s", err)
    - }
    -
    - if !reflect.DeepEqual(act, exp) {
    - t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", act, exp)
    - }
    -}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/v1/types.go Mon Apr 27 21:48:18 2020 -0500
    @@ -0,0 +1,126 @@
    +package v1
    +
    +type Address struct {
    + ID string `jsonapi:"primary,address"`
    +
    + Addressee string `jsonapi:"attr,addressee"`
    + City string `jsonapi:"attr,city"`
    + Country string `jsonapi:"attr,country"`
    + Line1 string `jsonapi:"attr,line_1"`
    + Line2 string `jsonapi:"attr,line_2"`
    + PhoneNumber string `jsonapi:"attr,phone_number"`
    + PostalCode string `jsonapi:"attr,postal_code"`
    + State string `jsonapi:"attr,state"`
    +}
    +
    +type User struct {
    + ID string `jsonapi:"primary,user"`
    +
    + FirstName string `jsonapi:"attr,first_name"`
    + LastName string `jsonapi:"attr,last_name"`
    + FullName string `jsonapi:"attr,full_name"`
    + Vanity string `jsonapi:"attr,vanity"`
    + Email string `jsonapi:"attr,email"`
    + About string `jsonapi:"attr,about"`
    + FacebookId string `jsonapi:"attr,facebook_id"`
    + Gender int `jsonapi:"attr,gender"`
    + HasPassword bool `jsonapi:"attr,has_password"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + ThumbURL string `jsonapi:"attr,thumb_url"`
    + YouTube string `jsonapi:"attr,youtube"`
    + Twitter string `jsonapi:"attr,twitter"`
    + Facebook string `jsonapi:"attr,facebook"`
    + IsEmailVerified bool `jsonapi:"attr,is_email_verified"`
    + IsSuspended bool `jsonapi:"attr,is_suspended"`
    + IsDeleted bool `jsonapi:"attr,is_deleted"`
    + IsNuked bool `jsonapi:"attr,is_nuked"`
    + Created string `jsonapi:"attr,created"`
    + URL string `jsonapi:"attr,url"`
    +
    + Pledges *Pledge `jsonapi:"relation,pledges"`
    +}
    +
    +type Pledge struct {
    + ID string `jsonapi:"primary,pledge"`
    +
    + AmountCents int `jsonapi:"attr,amount_cents"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + DeclinedSince string `jsonapi:"attr,declined_since"`
    + PledgeCapCents int `jsonapi:"attr,pledge_cap_cents"`
    + PatronPaysFees bool `jsonapi:"attr,patron_pays_fees"`
    +
    + TotalHistoricalAmountCents *int `jsonapi:"attr,total_historical_amount_cents,omitempty"`
    + IsPaused *bool `jsonapi:"attr,is_paused,omitempty"`
    + HasShippingAddress *bool `jsonapi:"attr,has_shipping_address,omitempty"`
    + OutstandingPaymentAmountCents *int `jsonapi:"attr,outstanding_payment_amount_cents,omitempty"`
    +
    + Patron *User `jsonapi:"relation,patron"`
    + Reward *Reward `jsonapi:"relation,reward"`
    + Creator *User `jsonapi:"relation,creator"`
    + Address *Address `jsonapi:"relation,address"`
    +}
    +
    +type Reward struct {
    + ID string `jsonapi:"primary,reward"`
    +
    + Amount int `jsonapi:"attr,amount"`
    + AmountCents int `jsonapi:"attr,amount_cents"`
    + CreatedAt string `jsonapi:"attr,created_at,iso8601"`
    + DeletedAt string `jsonapi:"attr,deleted_at,iso8601,omitempty"`
    + EditedAt string `jsonapi:"attr,edited_at,iso8601"`
    + Description string `jsonapi:"attr,description"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + PatronCount int `jsonapi:"attr,patron_count"`
    + PostCount int `jsonapi:"attr,post_count"`
    + Published bool `jsonapi:"attr,published"`
    + PublishedAt string `jsonapi:"attr,published_at,iso8601"`
    + RequiresShipping bool `jsonapi:"attr,requires_shipping"`
    + Title string `jsonapi:"attr,title"`
    + UnpublishedAt string `jsonapi:"attr,unpublished_at,iso8601,omitempty"`
    + URL string `jsonapi:"attr,url"`
    +}
    +
    +type Campaign struct {
    + ID string `jsonapi:"primary,campaign"`
    +
    + Summary string `jsonapi:"attr,summary"`
    + CreationName string `jsonapi:"attr,creation_name"`
    + DisplayPatronGoals bool `jsonapi:"attr,display_patron_goals"`
    + PayPerName string `jsonapi:"attr,pay_per_name"`
    + OneLiner string `jsonapi:"attr,one_liner"`
    + MainVideoEmbed string `jsonapi:"attr,main_video_embed"`
    + MainVideoURL string `jsonapi:"attr,main_video_url"`
    + ImageSmallURL string `jsonapi:"attr,image_small_url"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + ThanksVideoURL string `jsonapi:"attr,thanks_video_url"`
    + ThanksEmbed string `jsonapi:"attr,thanks_embed"`
    + ThanksMsg string `jsonapi:"attr,thanks_msg"`
    + IsChargedImmediately bool `jsonapi:"attr,is_charged_immediately"`
    + IsMonthly bool `jsonapi:"attr,is_monthly"`
    + IsNsfw bool `jsonapi:"attr,is_nsfw"`
    + IsPlural bool `jsonapi:"attr,is_plural"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + PublishedAt string `jsonapi:"attr,published_at"`
    + PledgeURL string `jsonapi:"attr,pledge_url"`
    + PledgeSum int `jsonapi:"attr,pledge_sum"`
    + PatronCount int `jsonapi:"attr,patron_count"`
    + CreationCount int `jsonapi:"attr,creation_count"`
    + OutstandingPaymentAmountCents int `jsonapi:"attr,outstanding_payment_amount_cents"`
    +
    + Creator *User `jsonapi:"relation,creator,omitempty"`
    + Rewards []*Reward `jsonapi:"relation,rewards,omitempty"`
    + Goals []*Goal `jsonapi:"relation,goals,omitempty"`
    + Pledges []*Pledge `jsonapi:"relation,pledges,omitempty"`
    +}
    +
    +type Goal struct {
    + ID string `jsonapi:"primary,goal"`
    +
    + Amount int `jsonapi:"attr,amount"`
    + AmountCents int `jsonapi:"attr,amount_cents"`
    + CompletedPercentage int `jsonapi:"attr,completed_percentage"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + ReachedAt string `jsonapi:"attr,reached_at"`
    + Title string `jsonapi:"attr,title"`
    + Description string `jsonapi:"attr,description"`
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/v1/types_test.go Mon Apr 27 21:48:18 2020 -0500
    @@ -0,0 +1,140 @@
    +package v1
    +
    +import (
    + "reflect"
    + "strings"
    + "testing"
    +
    + "github.com/google/jsonapi"
    +)
    +
    +func TestAddressUnmarshal(t *testing.T) {
    + data := `{"data": {
    + "attributes": {
    + "addressee": "somebody",
    + "city": "somecity",
    + "country": "somecountry",
    + "line_1": "someline1",
    + "line_2": "someline2",
    + "phone_number": null,
    + "postal_code": "somepostalcode",
    + "state": "somestate"
    + },
    + "id": "someid",
    + "type": "address"
    +}}`
    +
    + exp := Address{
    + ID: "someid",
    + Addressee: "somebody",
    + City: "somecity",
    + Country: "somecountry",
    + Line1: "someline1",
    + Line2: "someline2",
    + PhoneNumber: "",
    + PostalCode: "somepostalcode",
    + State: "somestate",
    + }
    +
    + var address Address
    + err := jsonapi.UnmarshalPayload(strings.NewReader(data), &address)
    + if err != nil {
    + t.Errorf("unexpected error: %s", err)
    + }
    +
    + if !reflect.DeepEqual(address, exp) {
    + t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", address, exp)
    + }
    +}
    +
    +func TestRewardUnmarshal(t *testing.T) {
    + data := `{"data": {
    + "attributes": {
    + "amount": 100,
    + "amount_cents": 50,
    + "created_at": "2018-05-23T21:27:59.077755+00:00",
    + "deleted_at": null,
    + "edited_at": "2018-05-23T21:27:59.077755+00:00",
    + "description": "somedescription",
    + "image_url": "http://some.img",
    + "patron_count": 100,
    + "post_count": 50,
    + "published": true,
    + "published_at": "2018-05-23T21:27:59.077755+00:00",
    + "requires_shipping": true,
    + "title": "sometitle",
    + "unpublished_at": null,
    + "url": "http://some.reward"
    + },
    + "id": "someid",
    + "type": "reward"
    +}}`
    +
    + expDate := "2018-05-23T21:27:59.077755+00:00"
    +
    + exp := Reward{
    + ID: "someid",
    + Amount: 100,
    + AmountCents: 50,
    + CreatedAt: expDate,
    + EditedAt: expDate,
    + Description: "somedescription",
    + ImageURL: "http://some.img",
    + PatronCount: 100,
    + PostCount: 50,
    + Published: true,
    + PublishedAt: expDate,
    + RequiresShipping: true,
    + Title: "sometitle",
    + URL: "http://some.reward",
    + }
    +
    + var act Reward
    + err := jsonapi.UnmarshalPayload(strings.NewReader(data), &act)
    + if err != nil {
    + t.Errorf("unexpected error: %s", err)
    + }
    +
    + if !reflect.DeepEqual(act, exp) {
    + t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", act, exp)
    + }
    +}
    +
    +func TestGoalUnmarshal(t *testing.T) {
    + data := `{"data": {
    + "attributes": {
    + "amount": 100,
    + "amount_cents": 50,
    + "completed_percentage": 75,
    + "created_at": "2018-05-23T21:27:59.077755+00:00",
    + "reached_at": null,
    + "title": "sometitle",
    + "description": "somedescription"
    + },
    + "id": "someid",
    + "type": "goal"
    +}}`
    +
    + expDate := "2018-05-23T21:27:59.077755+00:00"
    +
    + exp := Goal{
    + ID: "someid",
    + Amount: 100,
    + AmountCents: 50,
    + CompletedPercentage: 75,
    + CreatedAt: expDate,
    + ReachedAt: "",
    + Title: "sometitle",
    + Description: "somedescription",
    + }
    +
    + var act Goal
    + err := jsonapi.UnmarshalPayload(strings.NewReader(data), &act)
    + if err != nil {
    + t.Errorf("unexpected error: %s", err)
    + }
    +
    + if !reflect.DeepEqual(act, exp) {
    + t.Errorf("value mismatch\n%#v\nis not equal to\n%#v", act, exp)
    + }
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/v2/types.go Mon Apr 27 21:48:18 2020 -0500
    @@ -0,0 +1,228 @@
    +package v2
    +
    +import (
    + "encoding/json"
    +)
    +
    +type Address struct {
    + ID string `jsonapi:"primary,address"`
    +
    + Addressee string `jsonapi:"attr,addressee"`
    + Line1 string `jsonapi:"attr,line_1"`
    + Line2 string `jsonapi:"attr,line_2"`
    + PostalCode string `jsonapi:"attr,postal_code"`
    + City string `jsonapi:"attr,city"`
    + State string `jsonapi:"attr,state"`
    + Country string `jsonapi:"attr,country"`
    + PhoneNumber string `jsonapi:"attr,phone_number"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    +
    + User *User `jsonapi:"relation,user,omitempty"`
    + Campaigns []*Campaign `jsonapi:"relation,campaigns,omitempty"`
    +}
    +
    +type Benefit struct {
    + ID string `jsonapi:"attr,primary,benefit"`
    + Title string `jsonapi:"attr,title"`
    + Description string `jsonapi:"attr,description"`
    + BenefitType string `jsonapi:"attr,benefit_type"`
    + RuleType string `jsonapi:"attr,rule_type"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + DeliveredDeliverablesCount int `jsonapi:"attr,delivered_deliverables_count"`
    + NotDeliveredDeliverablesCount int `jsonapi:"attr,not_delivered_deliverables_count"`
    + DeliverablesDueTodayCount int `jsonapi:"attr,deliverables_due_today_count"`
    + NextDeliverableDueDate string `jsonapi:"attr,next_deliverable_due_date"`
    + TiersCount int `jsonapi:"attr,tiers_count"`
    + IsDeleted bool `jsonapi:"attr,is_deleted"`
    + IsPublished bool `jsonapi:"attr,is_published"`
    + AppExternalID string `jsonapi:"attr,app_external_id"`
    + AppMeta *json.RawMessage `jsonapi:"attr,app_meta"`
    +
    + Tiers []*Tier `jsonapi:"relation,tiers,omitempty"`
    + Deliverables []*Deliverable `jsonapi:"relation,deliverables,omitempty"`
    + Campaign *Campaign `jsonapi:"relation,compaign,omitempty"`
    + // CampaignInstallation *CampaignInstallation `jsonapi:"relation,campaign_installation"`
    +}
    +
    +type Campaign struct {
    + ID string `jsonapi:"primary,campaign"`
    +
    + Summary string `jsonapi:"attr,summary"`
    + CreationName string `jsonapi:"attr,creation_name"`
    + PayPerName string `jsonapi:"attr,pay_per_name"`
    + OneLiner string `jsonapi:"attr,one_liner"`
    + MainVideoEmbed string `jsonapi:"attr,main_video_embed"`
    + MainVideoURL string `jsonapi:"attr,main_video_url"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + ImageSmallURL string `jsonapi:"attr,image_small_url"`
    + ThanksVideoURL string `jsonapi:"attr,thanks_video_url"`
    + ThanksEmbed string `jsonapi:"attr,thanks_embed"`
    + ThanksMsg string `jsonapi:"attr,thanks_msg"`
    + IsMonthly bool `jsonapi:"attr,is_monthly"`
    + HasRss bool `jsonapi:"attr,has_rss"`
    + HasSentRssNotify bool `jsonapi:"attr,has_sent_rss_notify"`
    + RssFeedTitle string `jsonapi:"attr,rss_feed_title"`
    + RssArtworkURL string `jsonapi:"attr,rss_artwork_url"`
    + IsNsfw bool `jsonapi:"attr,is_nsfw"`
    + IsChargedImmediately bool `jsonapi:"attr,is_charged_immediately"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + PublishedAt string `jsonapi:"attr,published_at"`
    + PledgeURL string `jsonapi:"attr,pledge_url"`
    + PatronCount int `jsonapi:"attr,patron_count"`
    + DiscordServerID string `jsonapi:"attr,discord_service_id"`
    + GoogleAnalyticsID string `jsonapi:"attr,google_analytics_id"`
    + EarningsVisibility string `jsonapi:"attr,earnings_visibility"`
    +
    + Tiers []*Tier `jsonapi:"relation,tiers,omitempty"`
    + Creator *User `jsonapi:"relation,creator,omitempty"`
    + Benefits []*Benefit `jsonapi:"relation,benefits,omitempty"`
    + Goals []*Goal `jsonapi:"relation,goals,omitempty"`
    +}
    +
    +type Deliverable struct {
    + ID string `jsonapi:"primary,deliverable"`
    +
    + CompletedAt string `jsonapi:"attr,completed_at"`
    + DeliveryStatus string `jsonapi:"attr,delivery_status"`
    + DueAt string `jsonapi:"attr,due_at"`
    +
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    + Benefit *Benefit `jsonapi:"relation,benefit,omitempty"`
    + Member *Member `jsonapi:"relation,member,omitempty"`
    + User *User `jsonapi:"relation,user,omitempty"`
    +}
    +
    +type Goal struct {
    + ID string `jsonapi:"primary,goal"`
    +
    + AmountCents int `jsonapi:"attr,amount_cents"`
    + Title string `jsonapi:"attr,title"`
    + Description string `jsonapi:"attr,description"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + ReachedAt string `jsonapi:"attr,reached_at"`
    + CompletedPercentage int `jsonapi:"attr,completed_percentage"`
    +
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    +}
    +
    +type Media struct {
    + ID string `jsonapi:"primary,media"`
    +
    + Filename string `jsonapi:"attr,file_name"`
    + SizeBytes int `jsonapi:"attr,size_bytes"`
    + MimeType string `jsonapi:"attr,mimetype"`
    + State string `jsonapi:"attr,state"`
    + OwnerType string `jsonapi:"attr,owner_type"`
    + OwnerID string `jsonapi:"attr,owner_id"`
    + OwnerRelationship string `jsonapi:"attr,owner_relationship"`
    + UploadExpiresAt string `jsonapi:"attr,upload_expires_at"`
    + UploadURL string `jsonapi:"attr,upload_url"`
    + UploadParameters *json.RawMessage `jsonapi:"attr,upload_parameters"`
    + DownloadURL string `jsonapi:"attr,download_url"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + Metadata *json.RawMessage `jsonapi:"attr,metadata"`
    +}
    +
    +type Member struct {
    + ID string `jsonapi:"primary,member"`
    +
    + PatronStatus string `jsonapi:"attr,patron_status"`
    + IsFollower bool `jsonapi:"attr,is_follower"`
    + FullName string `jsonapi:"attr,full_name"`
    + Email string `jsonapi:"attr,email"`
    + PledgeRelationshipStart string `jsonapi:"attr,pledge_relationship_start"`
    + LifetimeSupportCents int `jsonapi:"attr,lifetime_support_cents"`
    + CurrentlyEntitledAmountCents int `jsonapi:"attr,currently_entitled_amount_cents"`
    + LastChargeDate string `jsonapi:"attr,last_charge_date"`
    + LastChargeStatus string `jsonapi:"attr,last_charge_status"`
    + Note string `jsonapi:"attr,note"`
    + WillPayAmountCents int `jsonapi:"attr,will_pay_amount_cents"`
    +
    + Address *Address `jsonapi:"relation,address"`
    + Campaign *Campaign `jsonapi:"relation,campaign"`
    + CurrentlyEntitledTiers []*Tier `jsonapi:"relation,currently_entitled_tiers"`
    + User *User `jsonapi:"relation,user"`
    +}
    +
    +type OAuthClient struct {
    + ID string `jsonapi:"primary,oauthclient"`
    +
    + ClientSecret string `jsonapi:"attr,client_secret"`
    + Name string `jsonapi:"attr,name"`
    + Description string `jsonapi:"attr,description"`
    + AuthorName string `jsonapi:"attr,author_name"`
    + Domain string `jsonapi:"attr,domain"`
    + Version int `jsonapi:"attr,version"`
    + IconURL string `jsonapi:"attr,icon_url"`
    + PrivacyPolicyURL string `jsonapi:"attr,privacy_policy_url"`
    + TosURL string `jsonapi:"attr,tos_url"`
    + RedirectURIs string `jsonapi:"attr,redirect_uris"`
    + DefaultScopes string `jsonapi:"attr,default_scopes"`
    +
    + User *User `jsonapi:"relation,user,omitempty"`
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    + CreatorToken string `jsonapi:"relation,creator_token,omitempty"`
    + Apps []*PlatformApp `jsonapi:"relation,apps,omitempty"`
    +}
    +
    +type Tier struct {
    + ID string `jsonapi:"primary,tier"`
    +
    + AmountCents int `jsonapi:"attr,amount_cents"`
    + UserLimit int `jsonapi:"attr,user_limit"`
    + Remaining int `jsonapi:"attr,remaining"`
    + Description string `jsonapi:"attr,description"`
    + RequiresShipping bool `jsonapi:"attr,requires_shipping"`
    + CreatedAt string `jsonapi:"attr,created_at"`
    + URL string `jsonapi:"attr,url"`
    + PatronCount int `jsonapi:"attr,patron_count"`
    + PostCount int `jsonapi:"attr,post_count"`
    + DiscordRoleIDs *json.RawMessage `jsonapi:"attr,discord_role_ids"`
    + Title string `jsonapi:"attr,title"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + EditedAt string `jsonapi:"attr,edited_at"`
    + Published bool `jsonapi:"attr,published"`
    + PublishedAt string `jsonapi:"attr,published_at"`
    + UnpublishedAt string `jsonapi:"attr,unpublished_at"`
    +
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    + TierImage *Media `jsonapi:"relation,tier_image,omitempty"`
    + Benefits []*Benefit `jsonapi:"relation,benefits,omitempty"`
    +}
    +
    +type User struct {
    + ID string `jsonapi:"primary,user"`
    +
    + Email string `jsonapi:"attr,email"`
    + FirstName string `jsonapi:"attr,first_name"`
    + LastName string `jsonapi:"attr,last_name"`
    + FullName string `jsonapi:"attr,full_name"`
    + IsEmailVerified bool `jsonapi:"attr,is_email_verified"`
    + Vanity string `jsonapi:"attr,vanity"`
    + About string `jsonapi:"attr,about"`
    + ImageURL string `jsonapi:"attr,image_url"`
    + ThumbURL string `jsonapi:"attr,thumb_url"`
    + CanSeeNSFW bool `jsonapi:"attr,can_see_nsfw"`
    + Created string `jsonapi:"attr,created"`
    + URL string `jsonapi:"attr,url"`
    + LikeCount int `jsonapi:"attr,like_count"`
    + HidePledges bool `jsonapi:"attr,hide_pledges"`
    + SocialConnections *json.RawMessage `jsonapi:"attr,social_connections"`
    +
    + Memberships []*Member `jsonapi:"relation,memberships,omitempty"`
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    +}
    +
    +type Webhook struct {
    + ID string `jsonapi:"primary,webhook"`
    +
    + Triggers []string `jsonapi:"attr,triggers"`
    + URI string `jsonapi:"attr,uri"`
    + Paused bool `jsonapi:"attr,paused"`
    + LastAttemptedAt string `jsonapi:"attr,last_attempted_at"`
    + NumConsecutiveTimesFailed int `jsonapi:"attr,num_consecutive_times_failed"`
    + Secret string `jsonapi:"attr,secret"`
    +
    + Client *OAuthClient `jsonapi:"relation,client,omitempty"`
    + Campaign *Campaign `jsonapi:"relation,campaign,omitempty"`
    +}