friendship ended with social-app. php is my new best friend
1<?php
2/**
3 * Class Reddit
4 *
5 * @created 09.04.2024
6 * @author smiley <smiley@chillerlan.net>
7 * @copyright 2024 smiley
8 * @license MIT
9 *
10 * @noinspection PhpUnused
11 */
12declare(strict_types=1);
13
14namespace chillerlan\OAuth\Providers;
15
16use chillerlan\OAuth\Core\{
17 AuthenticatedUser, ClientCredentials, ClientCredentialsTrait, CSRFToken, OAuth2Interface,
18 OAuth2Provider, TokenInvalidate, TokenInvalidateTrait, TokenRefresh, UserInfo,
19};
20use Psr\Http\Message\ResponseInterface;
21use function sprintf;
22
23/**
24 * Reddit OAuth2
25 *
26 * @link https://github.com/reddit-archive/reddit/wiki/OAuth2
27 * @link https://github.com/reddit-archive/reddit/wiki/API
28 * @link https://support.reddithelp.com/hc/en-us/articles/16160319875092-Reddit-Data-API-Wiki
29 * @link https://github.com/reddit-archive/reddit/wiki/OAuth2#manually-revoking-a-token
30 * @link https://www.reddit.com/dev/api
31 */
32class Reddit extends OAuth2Provider implements ClientCredentials, CSRFToken, TokenRefresh, TokenInvalidate, UserInfo{
33 use ClientCredentialsTrait, TokenInvalidateTrait;
34
35 public const IDENTIFIER = 'REDDIT';
36
37 public const SCOPE_ACCOUNT = 'account';
38 public const SCOPE_CREDDITS = 'creddits';
39 public const SCOPE_EDIT = 'edit';
40 public const SCOPE_FLAIR = 'flair';
41 public const SCOPE_HISTORY = 'history';
42 public const SCOPE_IDENTITY = 'identity';
43 public const SCOPE_LIVEMANAGE = 'livemanage';
44 public const SCOPE_MODCONFIG = 'modconfig';
45 public const SCOPE_MODCONTRIBUTORS = 'modcontributors';
46 public const SCOPE_MODFLAIR = 'modflair';
47 public const SCOPE_MODLOG = 'modlog';
48 public const SCOPE_MODMAIL = 'modmail';
49 public const SCOPE_MODNOTE = 'modnote';
50 public const SCOPE_MODOTHERS = 'modothers';
51 public const SCOPE_MODPOSTS = 'modposts';
52 public const SCOPE_MODSELF = 'modself';
53 public const SCOPE_MODTRAFFIC = 'modtraffic';
54 public const SCOPE_MODWIKI = 'modwiki';
55 public const SCOPE_MYSUBREDDITS = 'mysubreddits';
56 public const SCOPE_PRIVATEMESSAGES = 'privatemessages';
57 public const SCOPE_READ = 'read';
58 public const SCOPE_REPORT = 'report';
59 public const SCOPE_SAVE = 'save';
60 public const SCOPE_STRUCTUREDSTYLES = 'structuredstyles';
61 public const SCOPE_SUBMIT = 'submit';
62 public const SCOPE_SUBSCRIBE = 'subscribe';
63 public const SCOPE_VOTE = 'vote';
64 public const SCOPE_WIKIEDIT = 'wikiedit';
65 public const SCOPE_WIKIREAD = 'wikiread';
66
67 public const DEFAULT_SCOPES = [
68 self::SCOPE_ACCOUNT,
69 self::SCOPE_IDENTITY,
70 self::SCOPE_READ,
71 ];
72
73 public const USER_AGENT = OAuth2Interface::USER_AGENT.' (by /u/chillerlan)';
74
75 public const HEADERS_AUTH = [
76 'User-Agent' => self::USER_AGENT,
77 ];
78
79 public const HEADERS_API = [
80 'User-Agent' => self::USER_AGENT,
81 ];
82
83 public const USES_BASIC_AUTH_IN_ACCESS_TOKEN_REQUEST = true;
84
85 protected string $authorizationURL = 'https://www.reddit.com/api/v1/authorize';
86 protected string $accessTokenURL = 'https://www.reddit.com/api/v1/access_token';
87 protected string $apiURL = 'https://oauth.reddit.com/api';
88 protected string $revokeURL = 'https://www.reddit.com/api/v1/revoke_token';
89 protected string|null $apiDocs = 'https://www.reddit.com/dev/api';
90 protected string|null $applicationURL = 'https://www.reddit.com/prefs/apps/';
91 protected string|null $userRevokeURL = 'https://www.reddit.com/settings/privacy';
92
93 /**
94 * @param array<string, scalar|bool|null> $body
95 */
96 protected function sendTokenInvalidateRequest(string $url, array $body):ResponseInterface{ // phpcs:ignore
97
98 $request = $this->requestFactory
99 ->createRequest('POST', $url)
100 ->withHeader('Content-Type', 'application/x-www-form-urlencoded')
101 ;
102
103 $request = $this->addBasicAuthHeader($request);
104 $request = $this->setRequestBody($body, $request);
105
106 return $this->http->sendRequest($request);
107 }
108
109 /** @codeCoverageIgnore */
110 public function me():AuthenticatedUser{
111 $json = $this->getMeResponseData('/v1/me');
112
113 $userdata = [
114 'data' => $json,
115 'avatar' => $json['subreddit']['icon_img'],
116 'handle' => $json['name'],
117 'displayName' => $json['subreddit']['title'],
118 'id' => $json['id'],
119 'url' => sprintf('https://www.reddit.com%s', $json['subreddit']['url']),
120 ];
121
122 return new AuthenticatedUser($userdata);
123 }
124
125}