Endpoint.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <?php
  2. /*
  3. * This file is a part of the DiscordPHP-Http project.
  4. *
  5. * Copyright (c) 2021-present David Cole <david.cole1340@gmail.com>
  6. *
  7. * This file is subject to the MIT license that is bundled
  8. * with this source code in the LICENSE file.
  9. */
  10. namespace Discord\Http;
  11. class Endpoint
  12. {
  13. // GET
  14. public const GATEWAY = 'gateway';
  15. // GET
  16. public const GATEWAY_BOT = self::GATEWAY.'/bot';
  17. // GET, POST, PUT
  18. public const GLOBAL_APPLICATION_COMMANDS = 'applications/:application_id/commands';
  19. // GET, PATCH, DELETE
  20. public const GLOBAL_APPLICATION_COMMAND = 'applications/:application_id/commands/:command_id';
  21. // GET, POST, PUT
  22. public const GUILD_APPLICATION_COMMANDS = 'applications/:application_id/guilds/:guild_id/commands';
  23. // GET, PUT
  24. public const GUILD_APPLICATION_COMMANDS_PERMISSIONS = 'applications/:application_id/guilds/:guild_id/commands/permissions';
  25. // GET, PATCH, DELETE
  26. public const GUILD_APPLICATION_COMMAND = 'applications/:application_id/guilds/:guild_id/commands/:command_id';
  27. // GET, PUT
  28. public const GUILD_APPLICATION_COMMAND_PERMISSIONS = 'applications/:application_id/guilds/:guild_id/commands/:command_id/permissions';
  29. // POST
  30. public const INTERACTION_RESPONSE = 'interactions/:interaction_id/:interaction_token/callback';
  31. // PATCH, DELETE
  32. public const ORIGINAL_INTERACTION_RESPONSE = 'webhooks/:application_id/:interaction_token/messages/@original';
  33. // POST
  34. public const CREATE_INTERACTION_FOLLOW_UP = 'webhooks/:application_id/:interaction_token';
  35. // PATCH, DELETE
  36. public const INTERACTION_FOLLOW_UP = 'webhooks/:application_id/:interaction_token/messages/:message_id';
  37. // GET
  38. public const AUDIT_LOG = 'guilds/:guild_id/audit-logs';
  39. // GET, PATCH, DELETE
  40. public const CHANNEL = 'channels/:channel_id';
  41. // GET, POST
  42. public const CHANNEL_MESSAGES = self::CHANNEL.'/messages';
  43. // GET, PATCH, DELETE
  44. public const CHANNEL_MESSAGE = self::CHANNEL.'/messages/:message_id';
  45. // POST
  46. public const CHANNEL_CROSSPOST_MESSAGE = self::CHANNEL.'/messages/:message_id/crosspost';
  47. // POST
  48. public const CHANNEL_MESSAGES_BULK_DELETE = self::CHANNEL.'/messages/bulk-delete';
  49. // PUT, DELETE
  50. public const CHANNEL_PERMISSIONS = self::CHANNEL.'/permissions/:overwrite_id';
  51. // GET, POST
  52. public const CHANNEL_INVITES = self::CHANNEL.'/invites';
  53. // POST
  54. public const CHANNEL_FOLLOW = self::CHANNEL.'/followers';
  55. // POST
  56. public const CHANNEL_TYPING = self::CHANNEL.'/typing';
  57. // GET
  58. public const CHANNEL_PINS = self::CHANNEL.'/pins';
  59. // PUT, DELETE
  60. public const CHANNEL_PIN = self::CHANNEL.'/pins/:message_id';
  61. // POST
  62. public const CHANNEL_THREADS = self::CHANNEL.'/threads';
  63. // POST
  64. public const CHANNEL_MESSAGE_THREADS = self::CHANNEL_MESSAGE.'/threads';
  65. // GET
  66. public const CHANNEL_THREADS_ACTIVE = self::CHANNEL_THREADS.'/active';
  67. // GET
  68. public const CHANNEL_THREADS_ARCHIVED_PUBLIC = self::CHANNEL_THREADS.'/archived/public';
  69. // GET
  70. public const CHANNEL_THREADS_ARCHIVED_PRIVATE = self::CHANNEL_THREADS.'/archived/private';
  71. // GET
  72. public const CHANNEL_THREADS_ARCHIVED_PRIVATE_ME = self::CHANNEL.'/users/@me/threads/archived/private';
  73. // GET, PATCH, DELETE
  74. public const THREAD = 'channels/:thread_id';
  75. // GET
  76. public const THREAD_MEMBERS = self::THREAD.'/thread-members';
  77. // GET, PUT, DELETE
  78. public const THREAD_MEMBER = self::THREAD_MEMBERS.'/:user_id';
  79. // PUT, DELETE
  80. public const THREAD_MEMBER_ME = self::THREAD_MEMBERS.'/@me';
  81. // GET, DELETE
  82. public const MESSAGE_REACTION_ALL = self::CHANNEL.'/messages/:message_id/reactions';
  83. // GET, DELETE
  84. public const MESSAGE_REACTION_EMOJI = self::CHANNEL.'/messages/:message_id/reactions/:emoji';
  85. // PUT, DELETE
  86. public const OWN_MESSAGE_REACTION = self::CHANNEL.'/messages/:message_id/reactions/:emoji/@me';
  87. // DELETE
  88. public const USER_MESSAGE_REACTION = self::CHANNEL.'/messages/:message_id/reactions/:emoji/:user_id';
  89. // GET, POST
  90. public const CHANNEL_WEBHOOKS = self::CHANNEL.'/webhooks';
  91. // POST
  92. public const GUILDS = 'guilds';
  93. // GET, PATCH, DELETE
  94. public const GUILD = 'guilds/:guild_id';
  95. // GET, POST, PATCH
  96. public const GUILD_CHANNELS = self::GUILD.'/channels';
  97. // GET
  98. public const GUILD_MEMBERS = self::GUILD.'/members';
  99. // GET
  100. public const GUILD_MEMBERS_SEARCH = self::GUILD.'/members/search';
  101. // GET, PATCH, PUT, DELETE
  102. public const GUILD_MEMBER = self::GUILD.'/members/:user_id';
  103. // PATCH
  104. public const GUILD_MEMBER_SELF = self::GUILD.'/members/@me';
  105. /** @deprecated 9.0.9 Use `GUILD_MEMBER_SELF` */
  106. public const GUILD_MEMBER_SELF_NICK = self::GUILD.'/members/@me/nick';
  107. // PUT, DELETE
  108. public const GUILD_MEMBER_ROLE = self::GUILD.'/members/:user_id/roles/:role_id';
  109. // GET
  110. public const GUILD_BANS = self::GUILD.'/bans';
  111. // GET, PUT, DELETE
  112. public const GUILD_BAN = self::GUILD.'/bans/:user_id';
  113. // GET, PATCH
  114. public const GUILD_ROLES = self::GUILD.'/roles';
  115. // GET, POST, PATCH, DELETE
  116. public const GUILD_ROLE = self::GUILD.'/roles/:role_id';
  117. // POST
  118. public const GUILD_MFA = self::GUILD.'/mfa';
  119. // GET, POST
  120. public const GUILD_INVITES = self::GUILD.'/invites';
  121. // GET, POST
  122. public const GUILD_INTEGRATIONS = self::GUILD.'/integrations';
  123. // PATCH, DELETE
  124. public const GUILD_INTEGRATION = self::GUILD.'/integrations/:integration_id';
  125. // POST
  126. public const GUILD_INTEGRATION_SYNC = self::GUILD.'/integrations/:integration_id/sync';
  127. // GET, POST
  128. public const GUILD_EMOJIS = self::GUILD.'/emojis';
  129. // GET, PATCH, DELETE
  130. public const GUILD_EMOJI = self::GUILD.'/emojis/:emoji_id';
  131. // GET
  132. public const GUILD_PREVIEW = self::GUILD.'/preview';
  133. // GET, POST
  134. public const GUILD_PRUNE = self::GUILD.'/prune';
  135. // GET
  136. public const GUILD_REGIONS = self::GUILD.'/regions';
  137. // GET, PATCH
  138. public const GUILD_WIDGET_SETTINGS = self::GUILD.'/widget';
  139. // GET
  140. public const GUILD_WIDGET = self::GUILD.'/widget.json';
  141. // GET
  142. public const GUILD_WIDGET_IMAGE = self::GUILD.'/widget.png';
  143. // GET, PATCH
  144. public const GUILD_WELCOME_SCREEN = self::GUILD.'/welcome-screen';
  145. // PATCH
  146. public const GUILD_USER_CURRENT_VOICE_STATE = self::GUILD.'/voice-states/@me';
  147. // PATCH
  148. public const GUILD_USER_VOICE_STATE = self::GUILD.'/voice-states/:user_id';
  149. // GET
  150. public const GUILD_VANITY_URL = self::GUILD.'/vanity-url';
  151. // GET, PATCH
  152. public const GUILD_MEMBERSHIP_SCREENING = self::GUILD.'/member-verification';
  153. // GET
  154. public const GUILD_WEBHOOKS = self::GUILD.'/webhooks';
  155. // GET, POST
  156. public const GUILD_STICKERS = self::GUILD.'/stickers';
  157. // GET, PATCH, DELETE
  158. public const GUILD_STICKER = self::GUILD.'/stickers/:sticker_id';
  159. // GET
  160. public const STICKER = 'stickers/:sticker_id';
  161. // GET
  162. public const STICKER_PACKS = 'sticker-packs';
  163. // GET, POST
  164. public const GUILD_SCHEDULED_EVENTS = self::GUILD.'/scheduled-events';
  165. // GET, PATCH, DELETE
  166. public const GUILD_SCHEDULED_EVENT = self::GUILD.'/scheduled-events/:guild_scheduled_event_id';
  167. // GET
  168. public const GUILD_SCHEDULED_EVENT_USERS = self::GUILD.'/scheduled-events/:guild_scheduled_event_id/users';
  169. // GET, DELETE
  170. public const INVITE = 'invites/:code';
  171. // POST
  172. public const STAGE_INSTANCES = 'stage-instances';
  173. // GET, PATCH, DELETE
  174. public const STAGE_INSTANCE = 'stage-instances/:channel_id';
  175. // GET, POST
  176. public const GUILDS_TEMPLATE = self::GUILDS.'/templates/:template_code';
  177. // GET, POST
  178. public const GUILD_TEMPLATES = self::GUILD.'/templates';
  179. // PUT, PATCH, DELETE
  180. public const GUILD_TEMPLATE = self::GUILD.'/templates/:template_code';
  181. // GET, POST
  182. public const GUILD_AUTO_MODERATION_RULES = self::GUILD.'/auto-moderation/rules';
  183. // GET, PATCH, DELETE
  184. public const GUILD_AUTO_MODERATION_RULE = self::GUILD.'/auto-moderation/rules/:auto_moderation_rule_id';
  185. // GET, PATCH
  186. public const USER_CURRENT = 'users/@me';
  187. // GET
  188. public const USER = 'users/:user_id';
  189. // GET
  190. public const USER_CURRENT_GUILDS = self::USER_CURRENT.'/guilds';
  191. // DELETE
  192. public const USER_CURRENT_GUILD = self::USER_CURRENT.'/guilds/:guild_id';
  193. // GET
  194. public const USER_CURRENT_MEMBER = self::USER_CURRENT.'/guilds/:guild_id/member';
  195. // GET, POST
  196. public const USER_CURRENT_CHANNELS = self::USER_CURRENT.'/channels';
  197. // GET
  198. public const USER_CURRENT_CONNECTIONS = self::USER_CURRENT.'/connections';
  199. // GET, PUT
  200. public const USER_CURRENT_APPLICATION_ROLE_CONNECTION = self::USER_CURRENT.'/applications/:application_id/role-connection';
  201. // GET
  202. public const APPLICATION_CURRENT = 'oauth2/applications/@me';
  203. // GET, PATCH, DELETE
  204. public const WEBHOOK = 'webhooks/:webhook_id';
  205. // GET, PATCH, DELETE
  206. public const WEBHOOK_TOKEN = 'webhooks/:webhook_id/:webhook_token';
  207. // POST
  208. public const WEBHOOK_EXECUTE = self::WEBHOOK_TOKEN;
  209. // POST
  210. public const WEBHOOK_EXECUTE_SLACK = self::WEBHOOK_EXECUTE.'/slack';
  211. // POST
  212. public const WEBHOOK_EXECUTE_GITHUB = self::WEBHOOK_EXECUTE.'/github';
  213. // PATCH, DELETE
  214. public const WEBHOOK_MESSAGE = self::WEBHOOK_TOKEN.'/messages/:message_id';
  215. // GET, PUT
  216. public const APPLICATION_ROLE_CONNECTION_METADATA = 'applications/:application_id/role-connections/metadata';
  217. /**
  218. * Regex to identify parameters in endpoints.
  219. *
  220. * @var string
  221. */
  222. public const REGEX = '/:([^\/]*)/';
  223. /**
  224. * A list of parameters considered 'major' by Discord.
  225. *
  226. * @see https://discord.com/developers/docs/topics/rate-limits
  227. * @var string[]
  228. */
  229. public const MAJOR_PARAMETERS = ['channel_id', 'guild_id', 'webhook_id', 'thread_id'];
  230. /**
  231. * The string version of the endpoint, including all parameters.
  232. *
  233. * @var string
  234. */
  235. protected $endpoint;
  236. /**
  237. * Array of placeholders to be replaced in the endpoint.
  238. *
  239. * @var string[]
  240. */
  241. protected $vars = [];
  242. /**
  243. * Array of arguments to substitute into the endpoint.
  244. *
  245. * @var string[]
  246. */
  247. protected $args = [];
  248. /**
  249. * Array of query data to be appended
  250. * to the end of the endpoint with `http_build_query`.
  251. *
  252. * @var array
  253. */
  254. protected $query = [];
  255. /**
  256. * Creates an endpoint class.
  257. *
  258. * @param string $endpoint
  259. */
  260. public function __construct(string $endpoint)
  261. {
  262. $this->endpoint = $endpoint;
  263. if (preg_match_all(self::REGEX, $endpoint, $vars)) {
  264. $this->vars = $vars[1] ?? [];
  265. }
  266. }
  267. /**
  268. * Binds a list of arguments to the endpoint.
  269. *
  270. * @param string[] ...$args
  271. * @return this
  272. */
  273. public function bindArgs(...$args): self
  274. {
  275. for ($i = 0; $i < count($this->vars) && $i < count($args); $i++) {
  276. $this->args[$this->vars[$i]] = $args[$i];
  277. }
  278. return $this;
  279. }
  280. /**
  281. * Binds an associative array to the endpoint.
  282. *
  283. * @param string[] $args
  284. * @return this
  285. */
  286. public function bindAssoc(array $args): self
  287. {
  288. $this->args = array_merge($this->args, $args);
  289. return $this;
  290. }
  291. /**
  292. * Adds a key-value query pair to the endpoint.
  293. *
  294. * @param string $key
  295. * @param string|bool $value
  296. */
  297. public function addQuery(string $key, $value): void
  298. {
  299. if (! is_bool($value)) {
  300. $value = (string) $value;
  301. }
  302. $this->query[$key] = $value;
  303. }
  304. /**
  305. * Converts the endpoint into the absolute endpoint with
  306. * placeholders replaced.
  307. *
  308. * Passing a true boolean in will only replace the major parameters.
  309. * Used for rate limit buckets.
  310. *
  311. * @param bool $onlyMajorParameters
  312. * @return string
  313. */
  314. public function toAbsoluteEndpoint(bool $onlyMajorParameters = false): string
  315. {
  316. $endpoint = $this->endpoint;
  317. foreach ($this->vars as $var) {
  318. if (! isset($this->args[$var]) || ($onlyMajorParameters && ! $this->isMajorParameter($var))) {
  319. continue;
  320. }
  321. $endpoint = str_replace(":{$var}", $this->args[$var], $endpoint);
  322. }
  323. if (! $onlyMajorParameters && count($this->query) > 0) {
  324. $endpoint .= '?'.http_build_query($this->query);
  325. }
  326. return $endpoint;
  327. }
  328. /**
  329. * Converts the endpoint to a string.
  330. * Alias of ->toAbsoluteEndpoint();.
  331. *
  332. * @return string
  333. */
  334. public function __toString(): string
  335. {
  336. return $this->toAbsoluteEndpoint();
  337. }
  338. /**
  339. * Creates an endpoint class and binds arguments to
  340. * the newly created instance.
  341. *
  342. * @param string $endpoint
  343. * @param string[] $args
  344. * @return Endpoint
  345. */
  346. public static function bind(string $endpoint, ...$args)
  347. {
  348. $endpoint = new Endpoint($endpoint);
  349. $endpoint->bindArgs(...$args);
  350. return $endpoint;
  351. }
  352. /**
  353. * Checks if a parameter is a major parameter.
  354. *
  355. * @param string $param
  356. * @return bool
  357. */
  358. private static function isMajorParameter(string $param): bool
  359. {
  360. return in_array($param, self::MAJOR_PARAMETERS);
  361. }
  362. }