diff --git a/api/api.go b/api/api.go index e217771..ba7515d 100644 --- a/api/api.go +++ b/api/api.go @@ -9,6 +9,7 @@ import ( "go.fifitido.net/twitch/api/bits" "go.fifitido.net/twitch/api/channelpoints" "go.fifitido.net/twitch/api/channels" + "go.fifitido.net/twitch/api/charity" "go.fifitido.net/twitch/api/eventsub" ) @@ -23,6 +24,7 @@ type API struct { Bits *bits.Bits Channels *channels.Channels ChannelPoints *channelpoints.ChannelPoints + Charity *charity.Charity EventSub *eventsub.EventSub } @@ -39,6 +41,7 @@ func New() *API { Bits: bits.New(client, baseUrl), Channels: channels.New(client, baseUrl), ChannelPoints: channelpoints.New(client, baseUrl), + Charity: charity.New(client, baseUrl), EventSub: eventsub.New(client, baseUrl), } } diff --git a/api/charity/charity.go b/api/charity/charity.go new file mode 100644 index 0000000..8ac27b2 --- /dev/null +++ b/api/charity/charity.go @@ -0,0 +1,18 @@ +package charity + +import ( + "net/http" + "net/url" +) + +type Charity struct { + client *http.Client + baseUrl *url.URL +} + +func New(client *http.Client, baseUrl *url.URL) *Charity { + return &Charity{ + client: client, + baseUrl: baseUrl, + } +} diff --git a/api/charity/get_charity_campaign.go b/api/charity/get_charity_campaign.go new file mode 100644 index 0000000..b5616f7 --- /dev/null +++ b/api/charity/get_charity_campaign.go @@ -0,0 +1,71 @@ +package charity + +import ( + "encoding/json" + "net/url" + + "go.fifitido.net/twitch/api/types" +) + +type GetCharityCampaignResponse struct { + // A list that contains the charity campaign that the broadcaster is currently running. + // The list is empty if the broadcaster is not running a charity campaign; the campaign information is not available after the campaign ends. + Data []CharityCampaign `json:"data"` +} + +type CharityCampaign struct { + // An ID that identifies the charity campaign. + ID string `json:"id"` + + // An ID that identifies the broadcaster that’s running the campaign. + BroadcasterID string `json:"broadcaster_id"` + + // The broadcaster’s login name. + BroadcasterLogin string `json:"broadcaster_login"` + + // The broadcaster’s display name. + BroadcasterName string `json:"broadcaster_name"` + + // The charity’s name. + CharityName string `json:"charity_name"` + + // A description of the charity. + CharityDescription string `json:"charity_description"` + + // A URL to an image of the charity’s logo. The image’s type is PNG and its size is 100px X 100px. + CharityLogo string `json:"charity_logo"` + + // A URL to the charity’s website. + CharityWebsite string `json:"charity_website"` + + // The current amount of donations that the campaign has received. + CurrentAmount types.CurrencyAmount `json:"current_amount"` + + // The campaign’s fundraising goal. This field is null if the broadcaster has not defined a fundraising goal. + TargetAmount *types.CurrencyAmount `json:"target_amount"` +} + +// Gets information about the charity campaign that a broadcaster is running. +// For example, the campaign’s fundraising goal and the current amount of donations. +// +// To receive events when progress is made towards the campaign’s goal or the broadcaster changes the fundraising goal, +// subscribe to the channel.charity_campaign.progress subscription type. +// +// Requires a user access token that includes the channel:read:charity scope. +func (c *Charity) GetCharityCampaign(broadcasterID string) (*GetCharityCampaignResponse, error) { + endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "charity/campaigns", RawQuery: "broadcaster_id=" + broadcasterID}) + + resp, err := c.client.Get(endpoint.String()) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + + var data GetCharityCampaignResponse + if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { + return nil, err + } + + return &data, nil +} diff --git a/api/charity/get_charity_campaign_donations.go b/api/charity/get_charity_campaign_donations.go new file mode 100644 index 0000000..a856398 --- /dev/null +++ b/api/charity/get_charity_campaign_donations.go @@ -0,0 +1,74 @@ +package charity + +import ( + "encoding/json" + "net/url" + + "github.com/google/go-querystring/query" + "go.fifitido.net/twitch/api/types" +) + +type GetCharityCampaignDonationsParams struct { + // The ID of the broadcaster that’s currently running a charity campaign. This ID must match the user ID in the access token. + BroadcasterID string `json:"broadcaster_id"` + + // The maximum number of items to return per page in the response. The minimum page size is 1 item per page and the maximum is 100. The default is 20. + First *int `url:"first,omitempty"` + + // The cursor used to get the next page of results. The Pagination object in the response contains the cursor’s value. + // Read more: https://dev.twitch.tv/docs/api/guide#pagination + After *types.Cursor `url:"after,omitempty"` +} + +type GetCharityCampaignDonationsResponse struct { + // A list that contains the donations that users have made to the broadcaster’s charity campaign. + // The list is empty if the broadcaster is not currently running a charity campaign. + // The donation information is not available after the campaign ends. + Data []CharityCampaignDonation `json:"data"` + + // Contains the information used to page through the list of results. The object is empty if there are no more pages left to page through. + // Read more: https://dev.twitch.tv/docs/api/guide#pagination + Pagination types.Pagination `json:"pagination"` +} + +type CharityCampaignDonation struct { + // An ID that identifies the donation. The ID is unique across campaigns + ID string `json:"id"` + + // An ID that identifies the charity campaign that the donation applies to. + CampaignID string `json:"campaign_id"` + + // An ID that identifies a user that donated money to the campaign. + UserID string `json:"user_id"` + + // The user’s login name. + UserLogin string `json:"user_login"` + + // The user’s display name. + UserName string `json:"user_name"` + + // An object that contains the amount of money that the user donated. + Amount types.CurrencyAmount `json:"amount"` +} + +// Gets the list of donations that users have made to the broadcaster’s active charity campaign. +// +// To receive events as donations occur, subscribe to the channel.charity_campaign.donate subscription type. +// +// Requires a user access token that includes the channel:read:charity scope. +func (c *Charity) GetCharityCampaignDonations(params *GetCharityCampaignDonationsParams) (*GetCharityCampaignDonationsResponse, error) { + v, _ := query.Values(params) + endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "charity/campaigns/donations", RawQuery: v.Encode()}) + + resp, err := c.client.Get(endpoint.String()) + if err != nil { + return nil, err + } + + var respBody GetCharityCampaignDonationsResponse + if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil { + return nil, err + } + + return &respBody, nil +} diff --git a/api/types/types.go b/api/types/types.go index bfbb030..902285e 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -64,3 +64,20 @@ const ( SortOrderOldest SortOrder = "OLDEST" SortOrderNewest SortOrder = "NEWEST" ) + +// Currency Amount +type CurrencyAmount struct { + // The monetary amount. + // The amount is specified in the currency’s minor unit. + // For example, the minor units for USD is cents, so if the amount is $5.50 USD, value is set to 550. + Value int `json:"value"` + + // The number of decimal places used by the currency. For example, USD uses two decimal places. + // Use this number to translate value from minor units to major units by using the formula: + // + // value / 10^decimal_places + DecimalPlaces int `json:"decimal_places"` + + // The ISO-4217 three-letter currency code that identifies the type of currency in value. + Currency string `json:"currency"` +}