mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
131 lines
3.9 KiB
Ruby
131 lines
3.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Patreon
|
|
# Service to check Patreon patron status
|
|
class PatronChecker
|
|
attr_reader :user
|
|
|
|
def initialize(user)
|
|
@user = user
|
|
end
|
|
|
|
# Check if user is a patron of a specific creator
|
|
# @param creator_id [String] The Patreon creator ID
|
|
# @return [Boolean] true if user is an active patron
|
|
def patron_of?(creator_id)
|
|
memberships.any? do |membership|
|
|
membership.dig('relationships', 'campaign', 'data', 'id') == creator_id.to_s &&
|
|
membership.dig('attributes', 'patron_status') == 'active_patron'
|
|
end
|
|
end
|
|
|
|
# Get all active memberships
|
|
# @return [Array<Hash>] Array of membership data with campaign info
|
|
def memberships
|
|
@memberships ||= fetch_memberships
|
|
end
|
|
|
|
# Get detailed membership info for a specific creator
|
|
# @param creator_id [String] The Patreon creator ID
|
|
# @return [Hash, nil] Membership details or nil if not a patron
|
|
def membership_for(creator_id)
|
|
memberships.find do |membership|
|
|
membership.dig('relationships', 'campaign', 'data', 'id') == creator_id.to_s
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def fetch_memberships
|
|
return [] unless valid_token?
|
|
|
|
response = make_api_request
|
|
return [] unless response
|
|
|
|
extract_memberships(response)
|
|
rescue StandardError => e
|
|
Rails.logger.error("Failed to fetch Patreon memberships: #{e.message}")
|
|
[]
|
|
end
|
|
|
|
def valid_token?
|
|
return false if user.patreon_access_token.blank?
|
|
|
|
# Check if token is expired
|
|
if user.patreon_token_expires_at && user.patreon_token_expires_at < Time.current
|
|
refresh_token!
|
|
end
|
|
|
|
user.patreon_access_token.present?
|
|
end
|
|
|
|
def refresh_token!
|
|
return false if user.patreon_refresh_token.blank?
|
|
|
|
conn = Faraday.new(url: 'https://www.patreon.com') do |f|
|
|
f.request :url_encoded
|
|
f.response :json
|
|
f.adapter Faraday.default_adapter
|
|
end
|
|
|
|
response = conn.post('/api/oauth2/token') do |req|
|
|
req.body = {
|
|
grant_type: 'refresh_token',
|
|
refresh_token: user.patreon_refresh_token,
|
|
client_id: ENV['PATREON_CLIENT_ID'],
|
|
client_secret: ENV['PATREON_CLIENT_SECRET']
|
|
}
|
|
end
|
|
|
|
if response.success?
|
|
data = response.body
|
|
user.update(
|
|
patreon_access_token: data['access_token'],
|
|
patreon_refresh_token: data['refresh_token'],
|
|
patreon_token_expires_at: Time.current + data['expires_in'].seconds
|
|
)
|
|
true
|
|
else
|
|
Rails.logger.error("Failed to refresh Patreon token: #{response.body}")
|
|
false
|
|
end
|
|
rescue StandardError => e
|
|
Rails.logger.error("Error refreshing Patreon token: #{e.message}")
|
|
false
|
|
end
|
|
|
|
def make_api_request
|
|
conn = Faraday.new(url: 'https://www.patreon.com') do |f|
|
|
f.request :url_encoded
|
|
f.response :json
|
|
f.adapter Faraday.default_adapter
|
|
end
|
|
|
|
response = conn.get('/api/oauth2/v2/identity') do |req|
|
|
req.headers['Authorization'] = "Bearer #{user.patreon_access_token}"
|
|
req.params = {
|
|
include: 'memberships,memberships.campaign',
|
|
'fields[member]' => 'patron_status,pledge_relationship_start',
|
|
'fields[campaign]' => 'vanity,url'
|
|
}
|
|
end
|
|
|
|
response.success? ? response.body : nil
|
|
end
|
|
|
|
def extract_memberships(response)
|
|
return [] unless response['included']
|
|
|
|
memberships = response['included'].select { |item| item['type'] == 'member' }
|
|
campaigns = response['included'].select { |item| item['type'] == 'campaign' }
|
|
|
|
# Enrich memberships with campaign data
|
|
memberships.map do |membership|
|
|
campaign_id = membership.dig('relationships', 'campaign', 'data', 'id')
|
|
campaign = campaigns.find { |c| c['id'] == campaign_id }
|
|
|
|
membership.merge('campaign' => campaign) if campaign
|
|
end.compact
|
|
end
|
|
end
|
|
end
|