Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.0.0

* **Breaking** Library moved to use Patreon API v2 endpoints and calls
* A good part of the code is now generated based on the Platform API's Cartographer schema definition.

# 0.5.1

* Fix test runner to execute tests properly
Expand Down
75 changes: 66 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# patreon-ruby
Interact with the Patreon API via OAuth.

## Important notice about updating to 1.0.0 from earlier versions

Patreon Ruby library version 1.0.0 moves on to Patreon's v2 API, which is not compatible with old v1 calls. Therefore directly upgrading from older versions to 1.0.0 would break compatibility of your installation. APIv1 will be deprecated some time soon after APIv2 comes out of beta, so it's important to get your integration compatible with API v2.

For more information on the differences and similarities between v1 and v2, check out: https://docs.patreon.com/#what-39-s-new

## Getting started

Get the gem from [RubyGems](https://rubygems.org/gems/patreon)

Step 1. Get your client_id and client_secret
Expand Down Expand Up @@ -38,22 +46,71 @@ end

Step 3. (Optional) Customize your usage
---
`Patreon::API` instances have four methods:
* `fetch_user(includes=nil, fields=nil)`
* `fetch_campaign(includes=nil, fields=nil)`
* `fetch_campaign_and_patrons(includes=nil, fields=nil)`
* `fetch_page_of_pledges(campaign_id, page_size, cursor=nil, includes=nil, fields=nil)`
`Patreon::API` instances have the following methods:
<!--
This list is auto-generated from the same code that generates
https://docs.patreon.com.
-->
* `get_campaigns(opts = { includes: [], fields: [], count: 10, cursor: nil})`
* `get_identity(opts = { includes: [], fields: [], })`
* `get_webhooks(opts = { includes: [], fields: [], count: 10, cursor: nil})`
* `get_campaigns_by_id_members(resource_id, opts = { includes: [], fields: [], count: 10, cursor: nil})`
* `get_campaigns_by_id(resource_id, opts = { includes: [], fields: [], })`
* `get_webhooks_by_id(resource_id, opts = { includes: [], fields: [], })`
* `get_members_by_id(resource_id, opts = { includes: [], fields: [], })`

The `includes` and `fields` arguments to these methods specify
the [related resources](http://jsonapi.org/format/#fetching-includes)
and the [resource attributes](http://jsonapi.org/format/#fetching-sparse-fieldsets)
you want returned by our API, as per the [JSON:API specification](http://jsonapi.org/).
The lists of valid `includes` and `fields` arguments are provided on `Patreon::Schemas`.
For instance, if you wanted to request the total amount a patron has ever paid to your campaign,
which is not included by default, you could do:

For instance, if you wanted to request the first name and total amount a patron has ever paid to your campaign, you could do:
```ruby
api_client = Patreon::API.new(patron_access_token)
patron_response = api_client.fetch_user(nil, {
'pledge': Patreon::Schemas::Pledge.default_attributes + [Patreon::Schemas::Pledge::Attributes::TOTAL_HISTORICAL_AMOUNT_CENTS]

User = Patreon::Schemas::User
Member = Patreon::Schemas::Member

patron_response = api_client.get_identity({
includes: [User::Relationships::MEMBERSHIPS],
fields: {
User::Name => User::Attributes::FIRST_NAME,
Member::Name => Member::Attributes::LIFETIME_SUPPORT_CENTS
}
})
```
Which would return:
```json
{
"data": {
"attributes": {
"first_name": "Jack"
},
"id": "1234",
"relationships": {
"memberships": {
"data": [
{
"id": "960d87e4-49ab-4828-b411-8ba9f91c6d81",
"type": "member"
}
]
}
},
"type": "user"
},
"included": [
{
"attributes": {
"lifetime_support_cents": 500
},
"id": "960d87e4-49ab-4828-b411-8ba9f91c6d81",
"type": "member"
}
],
"links": {
"self": "https://www.patreon.com/api/oauth2/v2/user/1234"
}
}
```
24 changes: 18 additions & 6 deletions example/fetch_all_patrons.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,27 @@
# Fetching basic data
api_client = Patreon::API.new(access_token)

campaign_response = api_client.fetch_campaign()
Member = Patreon::Schemas::Member

campaign_response = api_client.get_campaigns()
campaign_id = campaign_response.data[0].id

# Fetching all pledges
all_pledges = []
all_members = []
cursor = nil
while true do
page_response = api_client.fetch_page_of_pledges(campaign_id, { :count => 25, :cursor => cursor })
all_pledges += page_response.data
page_response = api_client.get_campaigns_by_id_members(campaign_id, {
:count => 25,
:cursor => cursor,
# In v2 you need to specify the fields that you are requesting
fields: {
Member::Name => [
Member::Attributes::FULL_NAME,
Member::Attributes::LIFETIME_SUPPORT_CENTS,
],
}
})
all_members += page_response.data
next_page_link = page_response.links[page_response.data]['next']
if next_page_link
parsed_query = CGI::parse(next_page_link)
Expand All @@ -35,5 +47,5 @@
end

# Mapping to all patrons. Feel free to customize as needed.
# As with all standard Ruby objects, (pledge.methods - Object.methods) will list the available attributes and relationships
puts all_pledges.map{ |pledge| { full_name: pledge.patron.full_name, amount_cents: pledge.amount_cents } }
# As with all standard Ruby objects, (member.methods - Object.methods) will list the available attributes and relationships
puts all_members.map{ |member| { full_name: member.full_name, lifetime_support_cents: member.lifetime_support_cents } }
32 changes: 19 additions & 13 deletions example/sinatra/models/manager/patreon_user_mgr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,36 @@ def self.create_or_update_user_with_tokens(patreon_refresh_token, patreon_access
api_client = Patreon::API.new(patreon_access_token)

# Get the patron's profile info and pledge amount
user_response = api_client.fetch_user()
user_response = api_client.get_identity({
# In v2 you need to specify the fields that you are requesting
includes: [Patreon::Schemas::User::Relationships::MEMBERSHIPS],
fields: {
Patreon::Schemas::User::Name => [
Patreon::Schemas::User::Attributes::FULL_NAME,
Patreon::Schemas::User::Attributes::EMAIL,
],
Patreon::Schemas::Member::Name => [
Patreon::Schemas::Member::Attributes::LIFETIME_SUPPORT_CENTS
]
}
})
patreon_user_data = user_response.data
return nil unless patreon_user_data

# Find or make the user, and set their information using the API response
db_user = User.first_or_create({:patreon_user_id => patreon_user_data.id})
db_user.update({
update_data = {
:full_name => patreon_user_data.full_name,
:email => patreon_user_data.email,
:patreon_refresh_token => patreon_refresh_token,
:patreon_access_token => patreon_access_token
})

# Find the user's pledge to us, and if they have one, update their pledge amount in our db
# puts user_response.data.methods
pledges = (user_response.find_all('pledge') || [])
pledge = pledges.find {|obj|
obj.creator.id == MyConfig::PATREON_CREATOR_ID
}
if pledge
db_user.update({
:patreon_pledge_amount_cents => pledge.amount_cents
})
# If you request `memberships` and DON’T have the `identity.memberships` scope,
# you will receive data about the user’s membership to your campaign.
if patreon_user_data.memberships.length > 0
update_data[:lifetime_support_cents] = patreon_user_data.memberships[0].lifetime_support_cents
end
db_user.update(update_data)

# Return the user we've made or updated
return db_user
Expand Down
2 changes: 1 addition & 1 deletion example/sinatra/models/table/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class User
property :user_id, Serial
property :full_name, String
property :email, String
property :patreon_pledge_amount_cents, Integer
property :lifetime_support_cents, Integer
property :patreon_user_id, String
property :patreon_refresh_token, String
property :patreon_access_token, String
Expand Down
18 changes: 15 additions & 3 deletions lib/patreon.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# This file is auto-generated from the same code that generates
# https://docs.patreon.com. Community pull requests against this
# file may not be accepted.

require 'net/http'
require 'json'
require 'rack'
Expand All @@ -8,11 +12,19 @@
require 'patreon/utils/jsonapi/url_util'
require 'patreon/utils/enum'
require 'patreon/utils/client'
require 'patreon/schemas/address'
require 'patreon/schemas/benefit'
require 'patreon/schemas/campaign'
require 'patreon/schemas/deliverable'
require 'patreon/schemas/goal'
require 'patreon/schemas/pledge'
require 'patreon/schemas/reward'
require 'patreon/schemas/media'
require 'patreon/schemas/member'
require 'patreon/schemas/oauthclient'
require 'patreon/schemas/pledgeevent'
require 'patreon/schemas/post'
require 'patreon/schemas/tier'
require 'patreon/schemas/user'
require 'patreon/schemas/webhook'
require 'patreon/version'
require 'patreon/oauth'
require 'patreon/api'
require 'patreon/api'
58 changes: 42 additions & 16 deletions lib/patreon/api.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,55 @@
# This file is auto-generated from the same code that generates
# https://docs.patreon.com. Community pull requests against this
# file may not be accepted.

module Patreon
class API
include Patreon::Utils::JSONAPI

def initialize(access_token)
@access_token = access_token
end

def fetch_user(opts = {})
get_parse_json(Utils::JSONAPI::URLUtil.build_url('current_user', opts[:includes], opts[:fields]))
def get_campaigns(opts = {})
base_url = "campaigns"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields], opts[:count], opts[:cursor])
get_parse_json(url)
end

def get_identity(opts = {})
base_url = "identity"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields])
get_parse_json(url)
end

def get_webhooks(opts = {})
base_url = "webhooks"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields], opts[:count], opts[:cursor])
get_parse_json(url)
end

def get_campaigns_by_id_members(resource_id, opts = {})
base_url = "campaigns/#{resource_id}/members"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields], opts[:count], opts[:cursor])
get_parse_json(url)
end

def fetch_campaign(opts = {})
get_parse_json(Utils::JSONAPI::URLUtil.build_url('current_user/campaigns', opts[:includes], opts[:fields]))
def get_campaigns_by_id(resource_id, opts = {})
base_url = "campaigns/#{resource_id}"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields])
get_parse_json(url)
end

def fetch_campaign_and_patrons(opts = {})
opts[:includes] = opts[:includes] ? Array(opts[:includes]) : []
opts[:includes].concat(Schemas::Campaign.default_relationships + [Schemas::Campaign::Relationships::PLEDGES])
fetch_campaign(opts)
def get_webhooks_by_id(resource_id, opts = {})
base_url = "webhooks/#{resource_id}"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields])
get_parse_json(url)
end

def fetch_page_of_pledges(campaign_id, opts = {})
params = {}
params["page[count]"] = opts[:count] || 10
params["page[cursor]"] = opts[:cursor] if opts[:cursor]
url = "campaigns/#{campaign_id}/pledges?#{Rack::Utils.build_query(params)}"
get_parse_json(Patreon::Utils::JSONAPI::URLUtil.build_url(url, opts[:includes], opts[:fields]))
def get_members_by_id(resource_id, opts = {})
base_url = "members/#{resource_id}"
url = URLUtil.build_url(base_url, opts[:includes], opts[:fields])
get_parse_json(url)
end

private
Expand All @@ -43,7 +69,7 @@ def get_json(suffix)
#SECURITY HOLE
http.set_debug_output($stdout) if ENV['DEBUG']

req = Net::HTTP::Get.new("/api/oauth2/api/#{suffix}")
req = Net::HTTP::Get.new("/api/oauth2/v2/#{suffix}")
req['Authorization'] = "Bearer #{@access_token}"
req['User-Agent'] = Utils::Client.user_agent_string
http.request(req).body
Expand All @@ -53,4 +79,4 @@ def parse_json(json)
JSON::Api::Vanilla.parse(json)
end
end
end
end
32 changes: 32 additions & 0 deletions lib/patreon/schemas/address.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# This file is auto-generated from the same code that generates
# https://docs.patreon.com. Community pull requests against this
# file may not be accepted.

module Patreon
module Schemas
module Address
Name = 'address'

class Attributes
include Utils::Enum

define :ADDRESSEE, 'addressee'
define :LINE_1, 'line_1'
define :LINE_2, 'line_2'
define :POSTAL_CODE, 'postal_code'
define :CITY, 'city'
define :STATE, 'state'
define :COUNTRY, 'country'
define :PHONE_NUMBER, 'phone_number'
define :CREATED_AT, 'created_at'
end

class Relationships
include Utils::Enum

define :USER, 'user'
define :CAMPAIGNS, 'campaigns'
end
end
end
end
40 changes: 40 additions & 0 deletions lib/patreon/schemas/benefit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# This file is auto-generated from the same code that generates
# https://docs.patreon.com. Community pull requests against this
# file may not be accepted.

module Patreon
module Schemas
module Benefit
Name = 'benefit'

class Attributes
include Utils::Enum

define :TITLE, 'title'
define :DESCRIPTION, 'description'
define :BENEFIT_TYPE, 'benefit_type'
define :RULE_TYPE, 'rule_type'
define :CREATED_AT, 'created_at'
define :DELIVERED_DELIVERABLES_COUNT, 'delivered_deliverables_count'
define :NOT_DELIVERED_DELIVERABLES_COUNT, 'not_delivered_deliverables_count'
define :DELIVERABLES_DUE_TODAY_COUNT, 'deliverables_due_today_count'
define :NEXT_DELIVERABLE_DUE_DATE, 'next_deliverable_due_date'
define :TIERS_COUNT, 'tiers_count'
define :IS_DELETED, 'is_deleted'
define :IS_PUBLISHED, 'is_published'
define :IS_ENDED, 'is_ended'
define :APP_EXTERNAL_ID, 'app_external_id'
define :APP_META, 'app_meta'
end

class Relationships
include Utils::Enum

define :TIERS, 'tiers'
define :DELIVERABLES, 'deliverables'
define :CAMPAIGN, 'campaign'
define :CAMPAIGN_INSTALLATION, 'campaign_installation'
end
end
end
end
Loading