1
0
mirror of https://github.com/beestat/app.git synced 2025-05-23 18:04:14 -04:00
beestat/api/patreon.php
2023-08-29 22:35:39 -04:00

164 lines
5.3 KiB
PHP

<?php
/**
* High level functionality for interacting with the Patreon API.
*
* @author Jon Ziebell
*/
class patreon extends external_api {
public static $exposed = [
'private' => [
'authorize',
'initialize'
],
'public' => []
];
protected static $log_mysql = 'all';
protected static $cache = false;
protected static $cache_for = null;
/**
* If the original API call fails, the patreon token is updated outside of
* the current transaction to ensure it doesn't get rolled back due to an
* exception.
*
* The problem with that is that all subsequent API calls need this
* value...so it's stored here statically on the class and used instead of
* the old database value.
*/
protected static $patreon_token = null;
/**
* Redirect to Patreon to do the oAuth. Note: Put a space between scopes and
* urlencode the whole thing if it includes special characters.
*/
public function authorize() {
header('Location: https://www.patreon.com/oauth2/authorize?response_type=code&client_id=' . $this->setting->get('patreon_client_id') . '&redirect_uri=' . $this->setting->get('patreon_redirect_uri') . '&scope=identity');
}
/**
* Obtain the first set of tokens for a a patreon user, then sync that
* user's Patreon settings, then return code that closes the window.
*
* @param string $code The code used to get tokens from patreon with.
*/
public function initialize($code = null) {
if($code !== null) {
$this->api('patreon_token', 'obtain', ['code' => $code]);
$this->api('user', 'sync_patreon_status');
}
echo '<html><head><title></title></head><body><script type="text/javascript">window.close();</script></body></html><!--';
$this->request->set_headers([
'Content-Type' => 'text/html'
], true);
// Need to commit the transaction so the stuff gets saved.
$this->database->commit_transaction();
}
/**
* Send an API call to patreon and return the response.
*
* @param string $method GET or POST
* @param string $endpoint The API endpoint
* @param array $arguments POST or GET parameters
* @param boolean $auto_refresh_token Whether or not to automatically get a
* new token if the old one is expired.
*
* @return array The response of this API call.
*/
public function patreon_api($method, $endpoint, $arguments, $auto_refresh_token = true) {
$curl = [
'method' => $method
];
// Authorize/token endpoints don't use the /1/ in the URL. Everything else
// does.
$full_endpoint = $endpoint;
if ($full_endpoint !== 'authorize' && $full_endpoint !== 'token') {
$full_endpoint = '/v2/' . $full_endpoint;
// For non-authorization endpoints, add the access_token header. Will use
// provided token if set, otherwise will get the one for the logged in
// user.
if(self::$patreon_token === null) {
$patreon_tokens = $this->api(
'patreon_token',
'read',
[]
);
if(count($patreon_tokens) !== 1) {
throw new Exception('No token for this user');
}
$patreon_token = $patreon_tokens[0];
} else {
$patreon_token = self::$patreon_token;
}
$curl['header'] = [
'Authorization: Bearer ' . $patreon_token['access_token'],
'Content-Type: application/x-www-form-urlencoded'
];
}
else {
$full_endpoint = '/' . $full_endpoint;
}
$curl['url'] = 'https://www.patreon.com/api/oauth2' . $full_endpoint;
if ($method === 'GET') {
$curl['url'] .= '?' . http_build_query($arguments);
}
if ($method === 'POST') {
// Attach the client_id to all POST requests. It errors if you include it
// in a GET.
$arguments['client_id'] = $this->setting->get('patreon_client_id');
$curl['post_fields'] = http_build_query($arguments);
}
$curl_response = $this->curl($curl);
$response = json_decode($curl_response, true);
if ($response === null) {
// If this hasn't already been logged, log the error.
if($this::$log_mysql !== 'all') {
$this->log_mysql($curl_response);
}
throw new Exception('Invalid JSON');
}
// If the token was expired, refresh it and try again. Trying again sets
// auto_refresh_token to false to prevent accidental infinite refreshing if
// something bad happens.
if (isset($response['errors']) === true && $response['errors'][0]['status'] === '401') {
// Authentication token has expired. Refresh your tokens.
if ($auto_refresh_token === true) {
self::$patreon_token = $this->api('patreon_token', 'refresh');
return $this->patreon_api($method, $endpoint, $arguments, false);
}
else {
if($this::$log_mysql !== 'all') {
$this->log_mysql($curl_response);
}
throw new Exception($response['errors'][0]['detail']);
}
}
else if (isset($response['errors']) === true) {
// Any other error
if($this::$log_mysql !== 'all') {
$this->log_mysql($curl_response);
}
throw new Exception($response['errors'][0]['detail']);
}
else {
return $response;
}
}
}