From 372083d902fece9a2c5a20826b86fff0bc9ac41b Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 22:01:57 +0700 Subject: [PATCH 01/21] feat: remove most outdated legacy API stuff --- README.md | 2 +- src/TopPHP/API/Http.php | 1 - src/TopPHP/DBL.php | 93 +++++++------------------------ src/TopPHP/Structs/BaseStruct.php | 12 ++-- 4 files changed, 27 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d372951..355dd58 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ TopPHP uses composer to download. In order to install the library, use the follo * Enumerable constants for HTTP search lookups. * Flexible namespaces and interfaces for easily editing. * Up-to-standard package following the latest PSR. -* Automatic bot statistics POST requests. (Shards, guilds) +* Automatic bot statistics POST requests. (Guild count) ## Coming Soon diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 19f7be2..7b18450 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -23,7 +23,6 @@ class Http implements HttpStruct { public const BOT = "bots"; - public const USER = "users"; public const POST = "POST"; public const GET = "GET"; diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 2d5bfa7..3cd5315 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -57,12 +57,6 @@ final class DBL implements BaseStruct */ private $features; - /** - * @var bool - * @access public - */ - public $connected; - /** * Creates a DBL instance. * @@ -107,16 +101,11 @@ public function __construct(array $parameters) $this->port = (!$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; $this->api = new Request($this->token, $this->http); - /** Proxy an HTTP request to see if it works. */ - $_response = $this->api->req("GET", "/users/140862798832861184")["status"]; - if($_response === "200") $this->connected = true; - /** Finally do our feature checks from the parameters list. */ if($parameters["auto_stats"]) { $this->check_auto_stats( - $parameters["auto_stats"]["url"], - $parameters["auto_stats"]["id"] + $parameters["auto_stats"]["url"] ); } @@ -128,24 +117,18 @@ public function __construct(array $parameters) * This can only be done for a website URL. * * @param string $path The HTTP path you're using. - * @param int $id The bot ID. * @param array $values A list of values to be automatically posted. * @return void */ - protected function check_auto_stats(string $path, int $id, array $values) + protected function check_auto_stats(string $path, array $values) { try { - if($values["shards"]) $_json["shards"] = $values["shards"]; - if($values["shard_id"]) $_json["shard_id"] = $values["shard_id"]; - if($values["shard_count"]) $_json["shard_count"] = $values["shard_count"]; if($values["server_count"]) $_json["server_count"] = $values["server_count"]; else throw new MissingStatsException(); - $_id = ($id) ? $id : throw new MissingStatsException(); $_url = ($path) ? $path : throw new MissingStatsException(); - $_type = Http::BOT; - $_request = $this->api->req("POST", "/{$_type}/{$_id}/stats", $_json)["json"]; + $_request = $this->api->req("POST", "/bots/stats", $_json)["json"]; } catch(Exception $error) { echo $error; } @@ -171,104 +154,68 @@ protected function check_safety() } /** - * Shows the information from the specified type through a query search. + * Displays the general information of several bots. * - * @param string $type The search type. - * @param array $json The JSON query fields, with key:val as assoc. * @return array */ - public function show_info(string $type, array $json = []): array + public function get_bots(): array { - switch($type) - { - case Http::USER: - $_path = "users"; - break; - - case Http::BOT: - $_path = "bots"; - break; - - default: - die("Invalid search parameter: {$type}"); - break; - } - - return $this->api->req("GET", "/{$type}", $json)["json"]; + return $this->api->req("GET", "/bots", $json)["json"]; } /** - * Displays the general information about something - * given through the search type. + * Displays the general information about a bot. * - * @param string $type The search type. - * @param int $id The bot/user ID. + * @param int $id The bot ID. * @return array */ - public function find_info(string $type, int $id): array + public function get_bot(int $id): array { - switch($type) - { - case Http::USER: - $_path = "users"; - break; - - case Http::BOT: - $_path = "bots"; - break; - - default: - die("Invalid search parameter: {$type}"); - break; - } - - return $this->api->req("GET", "/{$type}/{$id}")["json"]; + return $this->api->req("GET", "/bots/{$id}")["json"]; } /** - * Returns the total votes of the bot. + * Returns the unique voters of the bot. * * @param int $id The bot ID. + * @param int $page The page counter. Starts from 1. * @return array */ - public function get_votes(int $id) + public function get_votes(int $id, int $page) { - return $this->api->req("GET", "/bots/{$id}/votes")["json"]; + return $this->api->req("GET", "/bots/{$id}/votes", ["page" => $page])["json"]; } /** * Returns a boolean check for if a user voted for your bot. * - * @param int $id The bot user ID. * @param int $user The user Snowflake ID. * @return array */ - public function get_user_vote(int $id, int $user): array + public function get_user_vote(int $user): array { - return $this->api->req("GET", "/bots/{$id}/check", ["userId" => $user])["json"]["voted"]; + return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"]; } /** * Returns the statistics of the bot. * - * @param int $id The bot ID. * @return array */ - public function get_stats(int $id): array + public function get_stats(): array { - return $this->api->req("GET", "/bots/{$id}/stats")["json"]; + return $this->api->req("GET", "/bots/stats")["json"]; } /** * Posts statistics to the bot's Top.gg page. * - * @param int $id The bot ID. * @param array $json The JSON query fields. * @return array */ - public function post_stats(int $id, array $json): array + public function post_stats(array $json): array { - return $this->api->req("POST", "/bots/{$id}/stats", $json)["json"]; + return $this->api->req("POST", "/bots/stats", $json)["json"]; } /** diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index 25bef85..1aee9a4 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -22,19 +22,19 @@ public function __construct(array $parameters); * procedures. */ /** Show statistics for all bots/users or specified. */ - public function show_info(string $type, array $json = []); - public function find_info(string $type, int $id); + public function get_bots(); + public function get_bot(int $id); /** Get information on the votes, vote check; and stats. */ - public function get_votes(int $id); - public function get_user_vote(int $id, int $user); - public function get_stats(int $id); + public function get_votes(int $id, int $page); + public function get_user_vote(int $user); + public function get_stats(); /** * POST requests will be handled here, and have to be * taken into account differently due to their nature. */ - public function post_stats(int $id, array $json); + public function post_stats(array $json); /** Accessor methods for private instances. */ public function getHttp(); From f6c600d993ae73ee6b1355a62fd6ddc1c2e81bb1 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 22:15:22 +0700 Subject: [PATCH 02/21] refactor: get_votes no longer require an $id argument --- src/TopPHP/DBL.php | 42 ++++++++++++++++++++++++++++--- src/TopPHP/Structs/BaseStruct.php | 2 +- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 3cd5315..3ea40ae 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -57,6 +57,12 @@ final class DBL implements BaseStruct */ private $features; + /** + * @var int + * @access private + */ + private $id; + /** * Creates a DBL instance. * @@ -101,6 +107,37 @@ public function __construct(array $parameters) $this->port = (!$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; $this->api = new Request($this->token, $this->http); + try { + $parts = explode('.', $this->token); + + if (count($parts) < 2) { + throw new Exception(); + } + + $encoded_json = $parts[1]; + $padding = 4 - (strlen($encoded_json) % 4); + + if ($padding < 4) { + $encoded_json .= str_repeat('=', $padding); + } + + $decoded_json = base64_decode($encoded_json, true); + + if ($decoded_json === false) { + throw new Exception(); + } + + $token_data = json_decode($decoded_json, true); + + if (!isset($token_data['id']) || !is_numeric($token_data['id'])) { + throw new Exception(); + } + + $this->id = intval($token_data['id']); + } catch (Exception $e) { + throw new MissingTokenException(); + } + /** Finally do our feature checks from the parameters list. */ if($parameters["auto_stats"]) { @@ -177,13 +214,12 @@ public function get_bot(int $id): array /** * Returns the unique voters of the bot. * - * @param int $id The bot ID. * @param int $page The page counter. Starts from 1. * @return array */ - public function get_votes(int $id, int $page) + public function get_votes(int $page) { - return $this->api->req("GET", "/bots/{$id}/votes", ["page" => $page])["json"]; + return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } /** diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index 1aee9a4..d02fe31 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -26,7 +26,7 @@ public function get_bots(); public function get_bot(int $id); /** Get information on the votes, vote check; and stats. */ - public function get_votes(int $id, int $page); + public function get_votes(int $page); public function get_user_vote(int $user); public function get_stats(); From b25670152026382ad159797e9d2e4a4ecdbf75d6 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 22:44:15 +0700 Subject: [PATCH 03/21] feat: add is_weekend --- src/TopPHP/API/Http.php | 4 ++-- src/TopPHP/API/Request.php | 4 ++-- src/TopPHP/DBL.php | 28 +++++++++++++++++++--------- src/TopPHP/Structs/BaseStruct.php | 3 ++- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 7b18450..9aa0521 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -90,8 +90,8 @@ public function call(string $type, string $path, array $payload = []): array $_headers = ($_type) ? get_headers($path) : "400"; $_response = substr($_headers[0], 9, 3); - if($_response === "401") $_response = "200"; // This is because the token is not being enforced. - if($_response === "429") + if ($_response === "401") $_response = "200"; // This is because the token is not being enforced. + if ($_response === "429") { /** * We have two specific ratelimit exceptions here. diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index 3b8b5c6..cc976e8 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -103,14 +103,14 @@ public function req(string $type, string $path = null, array $json = [], int $po * to receive information. */ $_request = @file_get_contents($_path, true, $_struct); - if(!$_request) $_error = true; + if (!$_request) $_error = true; } catch (Exception $error) { return $error; } finally { - if(!$_error) + if (!$_error) { // header("Content-Type: application/json"); // @http_response_code(intval($this->response) + 0); diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 3ea40ae..f5eeaea 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -97,10 +97,10 @@ public function __construct(array $parameters) "webhook" => [] ]; - if($parameters["auto_stats"]) $this->features["auto_stats"][0] = true; - if($parameters["safety"]) $this->features["safety"] = true; - if($parameters["webhook"]) $this->features["webhook"] = true; - if($parameters["token"]) $this->token = $parameters["token"]; + if ($parameters["auto_stats"]) $this->features["auto_stats"][0] = true; + if ($parameters["safety"]) $this->features["safety"] = true; + if ($parameters["webhook"]) $this->features["webhook"] = true; + if ($parameters["token"]) $this->token = $parameters["token"]; else throw new MissingTokenException(); $this->http = (!$parameters["webhook"]["url"]) ? Request::SERVER_ADDR : $parameters["webhook"]["url"]; @@ -139,7 +139,7 @@ public function __construct(array $parameters) } /** Finally do our feature checks from the parameters list. */ - if($parameters["auto_stats"]) + if ($parameters["auto_stats"]) { $this->check_auto_stats( $parameters["auto_stats"]["url"] @@ -161,7 +161,7 @@ protected function check_auto_stats(string $path, array $values) { try { - if($values["server_count"]) $_json["server_count"] = $values["server_count"]; + if ($values["server_count"]) $_json["server_count"] = $values["server_count"]; else throw new MissingStatsException(); $_url = ($path) ? $path : throw new MissingStatsException(); @@ -173,7 +173,7 @@ protected function check_auto_stats(string $path, array $values) finally { header("Content-Type: application/json"); - echo ""; + echo ""; } } @@ -187,7 +187,7 @@ protected function check_auto_stats(string $path, array $values) protected function check_safety() { /** One last time to check. */ - if($this->features["safety"]) die(); + if ($this->features["safety"]) die(); } /** @@ -217,7 +217,7 @@ public function get_bot(int $id): array * @param int $page The page counter. Starts from 1. * @return array */ - public function get_votes(int $page) + public function get_votes(int $page): array { return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } @@ -233,6 +233,16 @@ public function get_user_vote(int $user): array return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"]; } + /** + * Returns a boolean check for if the weekend multiplier is active, where a single vote counts as two. + * + * @return array + */ + public function is_weekend(): array + { + return $this->api->req("GET", "/weekend")["json"]["is_weekend"]; + } + /** * Returns the statistics of the bot. * diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index d02fe31..6c5a84f 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -25,9 +25,10 @@ public function __construct(array $parameters); public function get_bots(); public function get_bot(int $id); - /** Get information on the votes, vote check; and stats. */ + /** Get information on the votes, vote check, weekend multiplier, and stats. */ public function get_votes(int $page); public function get_user_vote(int $user); + public function is_weekend(); public function get_stats(); /** From ff40cc657d4a680daffe25fefb784a62d4ca2ca0 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 23:42:59 +0700 Subject: [PATCH 04/21] fix: make the library's HTTP requests actually work --- src/TopPHP/API/Http.php | 2 +- src/TopPHP/API/Request.php | 7 +++---- src/TopPHP/DBL.php | 7 +++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 9aa0521..462afa8 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -107,7 +107,7 @@ public function call(string $type, string $path, array $payload = []): array /** Now provide the information for the structure. */ $_path = ($_response === "200") ? $path : null; - $_payload = (!$payload) ? $payload : null; + $_payload = $payload ?? null; /** * All returned information will be formatted this way. diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index cc976e8..4d52800 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -73,11 +73,11 @@ public function __construct(string $token, string $http = self::SERVER_ADDR) public function req(string $type, string $path = null, array $json = [], int $port = self::SERVER_PORT): array { $_http = new Http($this->http, $port); - $_path = ($path) ? $_http->getHttp(), $path : null; + $_path = ($path) ? $_http->getHttp() . $path : ""; $_error = false; $_request = null; $_response = null; - $_json = (![]) ? http_build_query($json) : null; + $_json = ($json) ? http_build_query($json) : ""; try { @@ -88,7 +88,7 @@ public function req(string $type, string $path = null, array $json = [], int $po * Set up the HTTP request structure. * Will contextualize and create how we will interact. */ - $_path = $_path, $_json; + $_path = $_path . $_json; $_struct = [ "http" => [ "method" => $type, @@ -127,7 +127,6 @@ public function req(string $type, string $path = null, array $json = [], int $po else { - error_reporting(E_ALL); $_error = error_get_last(); /** diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index f5eeaea..53a2293 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -105,6 +105,9 @@ public function __construct(array $parameters) $this->http = (!$parameters["webhook"]["url"]) ? Request::SERVER_ADDR : $parameters["webhook"]["url"]; $this->port = (!$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; + + error_reporting(E_ALL); + $this->api = new Request($this->token, $this->http); try { @@ -138,6 +141,8 @@ public function __construct(array $parameters) throw new MissingTokenException(); } + error_reporting(0); + /** Finally do our feature checks from the parameters list. */ if ($parameters["auto_stats"]) { @@ -146,6 +151,8 @@ public function __construct(array $parameters) ); } + error_reporting(E_ALL); + $this->check_safety(); } From bcc8d864815ce2d08739234aa6f85e454b37f8b3 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 23:50:14 +0700 Subject: [PATCH 05/21] fix: fix get_bots() and get_votes() --- src/TopPHP/API/Request.php | 2 +- src/TopPHP/DBL.php | 10 +++++++--- src/TopPHP/Structs/BaseStruct.php | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index 4d52800..4ed3c10 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -77,7 +77,7 @@ public function req(string $type, string $path = null, array $json = [], int $po $_error = false; $_request = null; $_response = null; - $_json = ($json) ? http_build_query($json) : ""; + $_json = ($json) ? "?" . http_build_query($json) : ""; try { diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 53a2293..1eff047 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -202,9 +202,13 @@ protected function check_safety() * * @return array */ - public function get_bots(): array + public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array { - return $this->api->req("GET", "/bots", $json)["json"]; + return $this->api->req("GET", "/bots", [ + "limit" => $limit, + "offset" => $offset, + "sort" => $sort_by, + ])["json"]; } /** @@ -224,7 +228,7 @@ public function get_bot(int $id): array * @param int $page The page counter. Starts from 1. * @return array */ - public function get_votes(int $page): array + public function get_votes(int $page = 1): array { return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index 6c5a84f..28b842c 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -22,7 +22,7 @@ public function __construct(array $parameters); * procedures. */ /** Show statistics for all bots/users or specified. */ - public function get_bots(); + public function get_bots(int $limit, int $offset, string $sort_by); public function get_bot(int $id); /** Get information on the votes, vote check, weekend multiplier, and stats. */ From 5cdffefc68062d7c289fa15575e54b26fb431763 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 23:52:19 +0700 Subject: [PATCH 06/21] fix: fix is_weekend() and get_user_vote() --- src/TopPHP/DBL.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 1eff047..7ef9d43 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -225,7 +225,7 @@ public function get_bot(int $id): array /** * Returns the unique voters of the bot. * - * @param int $page The page counter. Starts from 1. + * @param int $page The page counter. Defaults to 1. * @return array */ public function get_votes(int $page = 1): array @@ -234,24 +234,24 @@ public function get_votes(int $page = 1): array } /** - * Returns a boolean check for if a user voted for your bot. + * Returns a boolean for if a user has voted for your bot. * * @param int $user The user Snowflake ID. * @return array */ public function get_user_vote(int $user): array { - return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"]; + return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]; } /** - * Returns a boolean check for if the weekend multiplier is active, where a single vote counts as two. + * Returns a boolean for if the weekend multiplier is active, where a single vote counts as two. * * @return array */ public function is_weekend(): array { - return $this->api->req("GET", "/weekend")["json"]["is_weekend"]; + return $this->api->req("GET", "/weekend")["json"]; } /** From d08b5d8e702c3c8b2bccbe69aa847e60757d067f Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 00:19:39 +0700 Subject: [PATCH 07/21] fix: fix post_stats() --- src/TopPHP/API/Http.php | 3 +-- src/TopPHP/API/Request.php | 21 +++++++------------ src/TopPHP/DBL.php | 31 +++++++++++----------------- src/TopPHP/Structs/BaseStruct.php | 2 +- src/TopPHP/Structs/RequestStruct.php | 2 +- 5 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 462afa8..ae8850e 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -107,7 +107,6 @@ public function call(string $type, string $path, array $payload = []): array /** Now provide the information for the structure. */ $_path = ($_response === "200") ? $path : null; - $_payload = $payload ?? null; /** * All returned information will be formatted this way. @@ -119,7 +118,7 @@ public function call(string $type, string $path, array $payload = []): array "type" => $_type, "path" => $_path, "status" => $_response, - "json" => $_payload + "json" => $payload ]; } diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index 4ed3c10..66427e9 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -70,14 +70,14 @@ public function __construct(string $token, string $http = self::SERVER_ADDR) * @param array $json Additional information you want to pass on as JSON. * @return array */ - public function req(string $type, string $path = null, array $json = [], int $port = self::SERVER_PORT): array + public function req(string $type, ?string $path = null, array $json = [], int $port = self::SERVER_PORT): array { $_http = new Http($this->http, $port); $_path = ($path) ? $_http->getHttp() . $path : ""; $_error = false; $_request = null; $_response = null; - $_json = ($json) ? "?" . http_build_query($json) : ""; + $_json = ($json && $type === "GET") ? "?" . http_build_query($json) : ""; try { @@ -96,14 +96,13 @@ public function req(string $type, string $path = null, array $json = [], int $po "Authorization: {$this->token}" . "\r\n" ] ]; - $_struct = @stream_context_create($_struct); - /** - * Here is where the official request is made - * to receive information. - */ + if ($json && $type !== "GET") { + $_struct["http"]["content"] = json_encode($json); + } + + $_struct = @stream_context_create($_struct); $_request = @file_get_contents($_path, true, $_struct); - if (!$_request) $_error = true; } catch (Exception $error) { return $error; } @@ -112,19 +111,15 @@ public function req(string $type, string $path = null, array $json = [], int $po { if (!$_error) { - // header("Content-Type: application/json"); - // @http_response_code(intval($this->response) + 0); - $_struct = $_http->call( $type, $_path, - json_decode($_request, true) + $_request ? json_decode($_request, true) : [] ); $this->cache = $_struct; return $_struct; } - else { $_error = error_get_last(); diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 7ef9d43..6fc6ae6 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -83,8 +83,6 @@ public function __construct(array $parameters) * KEKW. */ - error_reporting(0); - /** * Begin scanning through all of the possible accepted parameters. * PHP Warnings are thrown in the event that they're found to be as invalid keys @@ -97,17 +95,14 @@ public function __construct(array $parameters) "webhook" => [] ]; - if ($parameters["auto_stats"]) $this->features["auto_stats"][0] = true; - if ($parameters["safety"]) $this->features["safety"] = true; - if ($parameters["webhook"]) $this->features["webhook"] = true; - if ($parameters["token"]) $this->token = $parameters["token"]; + if (array_key_exists("auto_stats", $parameters) && $parameters["auto_stats"]) $this->features["auto_stats"][0] = true; + if (array_key_exists("safety", $parameters) && $parameters["safety"]) $this->features["safety"] = true; + if (array_key_exists("webhook", $parameters) && $parameters["webhook"]) $this->features["webhook"] = true; + if (array_key_exists("token", $parameters) && $parameters["token"]) $this->token = $parameters["token"]; else throw new MissingTokenException(); - $this->http = (!$parameters["webhook"]["url"]) ? Request::SERVER_ADDR : $parameters["webhook"]["url"]; - $this->port = (!$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; - - error_reporting(E_ALL); - + $this->http = (!array_key_exists("webhook", $parameters) || !array_key_exists("url", $parameters["webhook"]) || !$parameters["webhook"]["url"]) ? Request::SERVER_ADDR : $parameters["webhook"]["url"]; + $this->port = (!array_key_exists("webhook", $parameters) || !array_key_exists("port", $parameters["webhook"]) || !$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; $this->api = new Request($this->token, $this->http); try { @@ -141,18 +136,14 @@ public function __construct(array $parameters) throw new MissingTokenException(); } - error_reporting(0); - /** Finally do our feature checks from the parameters list. */ - if ($parameters["auto_stats"]) + if (array_key_exists("auto_stats", $parameters) && $parameters["auto_stats"]) { $this->check_auto_stats( $parameters["auto_stats"]["url"] ); } - error_reporting(E_ALL); - $this->check_safety(); } @@ -267,12 +258,14 @@ public function get_stats(): array /** * Posts statistics to the bot's Top.gg page. * - * @param array $json The JSON query fields. + * @param int $server_count Your bot's server count. * @return array */ - public function post_stats(array $json): array + public function post_stats(int $server_count): array { - return $this->api->req("POST", "/bots/stats", $json)["json"]; + return $this->api->req("POST", "/bots/stats", [ + "server_count" => $server_count, + ])["json"]; } /** diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index 28b842c..17c54af 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -35,7 +35,7 @@ public function get_stats(); * POST requests will be handled here, and have to be * taken into account differently due to their nature. */ - public function post_stats(array $json); + public function post_stats(int $server_count); /** Accessor methods for private instances. */ public function getHttp(); diff --git a/src/TopPHP/Structs/RequestStruct.php b/src/TopPHP/Structs/RequestStruct.php index dee2023..a3e9b0b 100644 --- a/src/TopPHP/Structs/RequestStruct.php +++ b/src/TopPHP/Structs/RequestStruct.php @@ -15,7 +15,7 @@ interface RequestStruct { public function __construct(string $token, string $http); - public function req(string $type, string $path = null, array $json = [], int $port = 80); + public function req(string $type, ?string $path = null, array $json = [], int $port = 80); /** Accessor methods for getting private instances. */ public function getContents(); From 5b1f372d42116cb546f624242c0ddbbaaefaa3d4 Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 00:27:32 +0700 Subject: [PATCH 08/21] fix: fix Exceptions --- src/TopPHP/API/Request.php | 2 +- src/TopPHP/DBL.php | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index 66427e9..ccfb40e 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -105,7 +105,7 @@ public function req(string $type, ?string $path = null, array $json = [], int $p $_request = @file_get_contents($_path, true, $_struct); } - catch (Exception $error) { return $error; } + catch (\Exception $error) { return $error; } finally { diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 6fc6ae6..59f9714 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -109,7 +109,7 @@ public function __construct(array $parameters) $parts = explode('.', $this->token); if (count($parts) < 2) { - throw new Exception(); + throw new \Exception(); } $encoded_json = $parts[1]; @@ -122,17 +122,17 @@ public function __construct(array $parameters) $decoded_json = base64_decode($encoded_json, true); if ($decoded_json === false) { - throw new Exception(); + throw new \Exception(); } $token_data = json_decode($decoded_json, true); if (!isset($token_data['id']) || !is_numeric($token_data['id'])) { - throw new Exception(); + throw new \Exception(); } $this->id = intval($token_data['id']); - } catch (Exception $e) { + } catch (\Exception $e) { throw new MissingTokenException(); } @@ -166,7 +166,7 @@ protected function check_auto_stats(string $path, array $values) $_request = $this->api->req("POST", "/bots/stats", $_json)["json"]; } - catch(Exception $error) { echo $error; } + catch(\Exception $error) { echo $error; } finally { @@ -263,6 +263,10 @@ public function get_stats(): array */ public function post_stats(int $server_count): array { + if (!$server_count || $server_count < 0) { + throw new \Exception("Server count must not be null, zero, or less."); + } + return $this->api->req("POST", "/bots/stats", [ "server_count" => $server_count, ])["json"]; From 50aeed4fb60d4a0fa49f68ca5b7cbde33658bb33 Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 00:35:18 +0700 Subject: [PATCH 09/21] feat: add additional constraints on get_bots() --- src/TopPHP/DBL.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 59f9714..98d8093 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -195,6 +195,22 @@ protected function check_safety() */ public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array { + if ($limit <= 0) { + $limit .= 1; + } else if ($limit > 500) { + $limit .= 500; + } + + if ($offset < 0) { + $offset .= 0; + } else if ($offset > 499) { + $offset .= 499; + } + + if ($sort_by !== "monthlyPoints" && $sort_by !== "date" && $sort_by !== "id") { + throw new \Exception("sort_by argument must be \"monthlyPoints\", \"date\", or \"id\"."); + } + return $this->api->req("GET", "/bots", [ "limit" => $limit, "offset" => $offset, From 795766fde2e6637f325ce6d69e6e760aa2f5ce0a Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 00:50:04 +0700 Subject: [PATCH 10/21] feat: add widgets --- src/TopPHP/DBL.php | 3 ++- src/TopPHP/Widget.php | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/TopPHP/Widget.php diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 98d8093..9be46b2 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -16,6 +16,7 @@ use DBL\API\Exceptions\MissingTokenException; use DBL\API\Exceptions\MissingStatsException; use DBL\Structs\BaseStruct; +use DBL\Widget; /** * Represents the TopPHP/Top.gg base class. @@ -191,7 +192,7 @@ protected function check_safety() /** * Displays the general information of several bots. * - * @return array + * @return array */ public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array { diff --git a/src/TopPHP/Widget.php b/src/TopPHP/Widget.php new file mode 100644 index 0000000..ac75759 --- /dev/null +++ b/src/TopPHP/Widget.php @@ -0,0 +1,49 @@ + \ No newline at end of file From dd9d56627a64755390078960899520075a27777b Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 00:57:55 +0700 Subject: [PATCH 11/21] doc: improve documentation --- src/TopPHP/API/Http.php | 4 ++-- src/TopPHP/API/Request.php | 3 --- src/TopPHP/DBL.php | 7 +++++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index ae8850e..72cc3e9 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -50,8 +50,8 @@ public function __construct(string $http, int $port = 80) * Has to meet with the constants of currently * accepted HTTP requests compatible with the API. * - * @param string $type The HTTP request you're using. - * @param string $path The HTTP path you're calling. + * @param string $type The HTTP request you're using. + * @param string $path The HTTP path you're calling. * @param array $payload Additional information you want to pass on as JSON. * @return array */ diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index ccfb40e..b66c5c7 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -81,9 +81,6 @@ public function req(string $type, ?string $path = null, array $json = [], int $p try { - /** Ensure headers are restored. */ - // header_remove("Content-Type"); - /** * Set up the HTTP request structure. * Will contextualize and create how we will interact. diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 9be46b2..92c14be 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -192,7 +192,10 @@ protected function check_safety() /** * Displays the general information of several bots. * - * @return array + * @param int $limit The maximum amount of bots to be queried. + * @param int $offset The amount of bots to be skipped. + * @param string $sort_by Sorts results based on a specific criteria. Results will always be descending. + * @return array */ public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array { @@ -275,7 +278,7 @@ public function get_stats(): array /** * Posts statistics to the bot's Top.gg page. * - * @param int $server_count Your bot's server count. + * @param int $server_count Your bot's server count. * @return array */ public function post_stats(int $server_count): array From 621ac91b59e1b9d03ac66ac309993582686e9a78 Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 19 Jun 2025 20:00:49 +0700 Subject: [PATCH 12/21] feat: tweak autoposter --- src/TopPHP/DBL.php | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 92c14be..134789d 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -141,7 +141,8 @@ public function __construct(array $parameters) if (array_key_exists("auto_stats", $parameters) && $parameters["auto_stats"]) { $this->check_auto_stats( - $parameters["auto_stats"]["url"] + $parameters["auto_stats"]["url"], + $parameters["auto_stats"]["callback"] ); } @@ -152,27 +153,21 @@ public function __construct(array $parameters) * Checks if stats should be posted to the website automatically. * This can only be done for a website URL. * - * @param string $path The HTTP path you're using. - * @param array $values A list of values to be automatically posted. + * @param string $url The HTTP path you're using. + * @param callable $callback The callback function that returns the bot's server count. * @return void */ - protected function check_auto_stats(string $path, array $values) + private function check_auto_stats(string $url, callable $callback) { try { - if ($values["server_count"]) $_json["server_count"] = $values["server_count"]; - else throw new MissingStatsException(); - - $_url = ($path) ? $path : throw new MissingStatsException(); - $_request = $this->api->req("POST", "/bots/stats", $_json)["json"]; + $this->post_stats($callback()); } - - catch(\Exception $error) { echo $error; } - + catch (\Exception $error) { echo $error; } finally { header("Content-Type: application/json"); - echo ""; + echo ""; } } From a43db30d0bec88076e2bb07379c66f98c4c6e4ad Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 20 Jun 2025 11:08:44 +0700 Subject: [PATCH 13/21] feat: use /discord/:type path for widgets --- src/TopPHP/Widget.php | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/TopPHP/Widget.php b/src/TopPHP/Widget.php index ac75759..07f2e83 100644 --- a/src/TopPHP/Widget.php +++ b/src/TopPHP/Widget.php @@ -2,47 +2,56 @@ namespace DBL; +enum WidgetType: string { + case DiscordBot = "discord/bot"; + case DiscordServer = "discord/server"; +} + final class Widget { private const BASE_URL = "https://top.gg/api/v1"; /** * Generates a large widget URL. * - * @param int $id The ID. + * @param WidgetType $ty The widget type. + * @param int $id The ID. * @return string */ - public static function large(int $id): string { - return self::BASE_URL . "/widgets/large/$id"; + public static function large(WidgetType $ty, int $id): string { + return self::BASE_URL . "/widgets/large/" . $ty->value . "/$id"; } /** * Generates a small widget URL for displaying votes. * - * @param int $id The ID. + * @param WidgetType $ty The widget type. + * @param int $id The ID. * @return string */ - public static function votes(int $id): string { - return self::BASE_URL . "/widgets/small/votes/$id"; + public static function votes(WidgetType $ty, int $id): string { + return self::BASE_URL . "/widgets/small/votes/" . $ty->value . "/$id"; } /** * Generates a small widget URL for displaying an entity's owner. * - * @param int $id The ID. + * @param WidgetType $ty The widget type. + * @param int $id The ID. * @return string */ - public static function owner(int $id): string { - return self::BASE_URL . "/widgets/small/owner/$id"; + public static function owner(WidgetType $ty, int $id): string { + return self::BASE_URL . "/widgets/small/owner/" . $ty->value . "/$id"; } /** * Generates a small widget URL for displaying social stats. * - * @param int $id The ID. + * @param WidgetType $ty The widget type. + * @param int $id The ID. * @return string */ - public static function social(int $id): string { - return self::BASE_URL . "/widgets/small/social/$id"; + public static function social(WidgetType $ty, int $id): string { + return self::BASE_URL . "/widgets/small/social/" . $ty->value . "/$id"; } } From 158ef269bfdde765198d0c90ddf702d784b13a50 Mon Sep 17 00:00:00 2001 From: null8626 Date: Mon, 23 Jun 2025 23:36:30 +0700 Subject: [PATCH 14/21] docs: readme overhaul --- README.md | 184 +++++++++++++++++++++++++++--- composer.json | 4 +- src/TopPHP/API/Http.php | 1 + src/TopPHP/API/Request.php | 3 +- src/TopPHP/DBL.php | 25 ++-- src/TopPHP/Structs/BaseStruct.php | 10 +- src/TopPHP/Webhook.php | 51 +++++++++ src/TopPHP/Widget.php | 10 ++ 8 files changed, 254 insertions(+), 34 deletions(-) create mode 100644 src/TopPHP/Webhook.php diff --git a/README.md b/README.md index 355dd58..7538c08 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,177 @@ -# TopPHP -A Top.gg API wrapper written in PHP 8. +# Top.gg PHP SDK -## Documentation -See [here](https://docs.top.gg/libraries/php/) for the official information. +The community-maintained PHP library for Top.gg. ## Installation -TopPHP uses composer to download. In order to install the library, use the following line: -`composer require top-gg/php-sdk` +```sh +$ composer require top-gg/php-sdk +``` -## Features +## Setting up -* Working GET and POST requests. -* Enumerable constants for HTTP search lookups. -* Flexible namespaces and interfaces for easily editing. -* Up-to-standard package following the latest PSR. -* Automatic bot statistics POST requests. (Guild count) +```php +include_once __DIR__ . "/vendor/autoload.php"; -## Coming Soon +use DBL\DBL; -* Webhooks -* Forced library global rate-limiting. +$client = new DBL([ + "token" => "Insert your Top.gg API token here." +]); +``` + +## Usage + +### Getting a bot + +```php +$bot = $client->get_bot(); +``` + +### Getting several bots + +#### With defaults + +```php +$bots = $client->get_bots(); +``` + +#### With explicit arguments + +```php +// Limit Offset Sort by +$bots = $client->get_bots(50, 0, "date"); +``` + +### Getting your bot's voters + +#### First page + +```php +$voters = $client->get_voters(); +``` + +#### Subsequent pages + +```php +$voters = $client->get_voters(2); +``` + +### Check if a user has voted for your bot + +```php +$has_voted = $client->has_voted(205680187394752512); +``` + +### Getting your bot's server count + +```php +$server_count = $client->get_server_count(); +``` + +### Posting your bot's server count + +```php +$client->post_server_count($bot->get_server_count()); +``` + +### Automatically posting your bot's server count every few minutes + +> **NOTE:** Considering PHP's shortcomings, this is only possible via a URL. + +In your original client declaration: + +```php +$client = new DBL([ + "token" => "Insert your Top.gg API token here.", + "auto_stats" => [ + "url": "Your URL", + "callback": => function () use ($bot) { + return $bot->get_server_count(); + } + ] +]); +``` + +### Checking if the weekend vote multiplier is active + +```php +$is_weekend = $client->is_weekend(); +``` + +### Generating widget URLs + +#### Large + +```php +use DBL\Widget; +use DBL\WidgetType; + +$widget_url = Widget::large(WidgetType::DiscordBot, 574652751745777665); +``` + +#### Votes + +```php +use DBL\Widget; +use DBL\WidgetType; + +$widget_url = Widget::votes(WidgetType::DiscordBot, 574652751745777665); +``` + +#### Owner + +```php +use DBL\Widget; +use DBL\WidgetType; + +$widget_url = Widget::owner(WidgetType::DiscordBot, 574652751745777665); +``` + +#### Social + +```php +use DBL\Widget; +use DBL\WidgetType; + +$widget_url = Widget::social(WidgetType::DiscordBot, 574652751745777665); +``` + +### Webhooks + +#### Being notified whenever someone voted for your bot + +**With Laravel:** + +In your `config/logging.php`: + +```php +"channels" => [ + "stdout" => [ + "driver" => "single", + "path" => "php://stdout", + "level" => "debug" + ] +] +``` + +In your `routes/api.php`: + +```php +use DBL\Webhook; + +use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Log; + +class MyVoteListener extends Webhook { + public function getAuthorization() { + return getenv("MY_TOPGG_WEBHOOK_SECRET"); + } + + public function callback(array $vote) { + Log::channel("stdout")->info("A user with the ID of " . $vote["user"] . " has voted us on Top.gg!"); + } +} + +Route::post('/votes', [MyVoteListener::class, "main"]); +``` \ No newline at end of file diff --git a/composer.json b/composer.json index 9a9ac10..930aed9 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,9 @@ "description": "The official Top.gg PHP API wrapper.", "license": "MIT", "require": { - "php": "^7.3|^8.0" + "php": "^7.3|^8.0", + "illuminate/routing": "^12.19", + "illuminate/http": "^12.19" }, "authors": [ { diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 72cc3e9..d46c800 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -11,6 +11,7 @@ */ namespace DBL\API; + use DBL\Structs\HttpStruct; /** diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index b66c5c7..f32ddd9 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -11,6 +11,7 @@ */ namespace DBL\API; + use DBL\API\Http; use DBL\Structs\RequestStruct; @@ -37,7 +38,7 @@ class Request implements RequestStruct /** @var string */ private $response; - public const SERVER_ADDR = "https://top.gg/api"; + public const SERVER_ADDR = "https://top.gg/api/v1"; public const SERVER_PORT = 80; /** diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 134789d..8085671 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -11,11 +11,13 @@ */ namespace DBL; + use DBL\API\Http; use DBL\API\Request; use DBL\API\Exceptions\MissingTokenException; use DBL\API\Exceptions\MissingStatsException; use DBL\Structs\BaseStruct; +use DBL\Webhook; use DBL\Widget; /** @@ -161,7 +163,7 @@ private function check_auto_stats(string $url, callable $callback) { try { - $this->post_stats($callback()); + $this->post_server_count($callback()); } catch (\Exception $error) { echo $error; } finally @@ -234,7 +236,7 @@ public function get_bot(int $id): array * @param int $page The page counter. Defaults to 1. * @return array */ - public function get_votes(int $page = 1): array + public function get_voters(int $page = 1): array { return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } @@ -245,7 +247,7 @@ public function get_votes(int $page = 1): array * @param int $user The user Snowflake ID. * @return array */ - public function get_user_vote(int $user): array + public function has_voted(int $user): array { return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]; } @@ -261,30 +263,29 @@ public function is_weekend(): array } /** - * Returns the statistics of the bot. + * Returns your bot's posted server count. * - * @return array + * @return int */ - public function get_stats(): array + public function get_server_count(): int { - return $this->api->req("GET", "/bots/stats")["json"]; + return $this->api->req("GET", "/bots/stats")["json"]["server_count"]; } /** - * Posts statistics to the bot's Top.gg page. + * Posts your bot's server count to Top.gg. * * @param int $server_count Your bot's server count. - * @return array */ - public function post_stats(int $server_count): array + public function post_server_count(int $server_count) { if (!$server_count || $server_count < 0) { throw new \Exception("Server count must not be null, zero, or less."); } - return $this->api->req("POST", "/bots/stats", [ + $this->api->req("POST", "/bots/stats", [ "server_count" => $server_count, - ])["json"]; + ]); } /** diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index 17c54af..dc1d7cc 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -25,17 +25,17 @@ public function __construct(array $parameters); public function get_bots(int $limit, int $offset, string $sort_by); public function get_bot(int $id); - /** Get information on the votes, vote check, weekend multiplier, and stats. */ - public function get_votes(int $page); - public function get_user_vote(int $user); + /** Get information on your voters, vote check, weekend multiplier, and stats. */ + public function get_voters(int $page); + public function has_voted(int $user); public function is_weekend(); - public function get_stats(); + public function get_server_count(); /** * POST requests will be handled here, and have to be * taken into account differently due to their nature. */ - public function post_stats(int $server_count); + public function post_server_count(int $server_count); /** Accessor methods for private instances. */ public function getHttp(); diff --git a/src/TopPHP/Webhook.php b/src/TopPHP/Webhook.php new file mode 100644 index 0000000..fc35408 --- /dev/null +++ b/src/TopPHP/Webhook.php @@ -0,0 +1,51 @@ +header("Authorization") !== $this->getAuthorization()) { + return response("Unauthorized", 401); + } + + $data = $request->json()->all(); + + if (!empty($data)) { + $this->callback($data); + + return response("", 204); + } + + return response("Bad request", 400); + } + + /** + * Retrieves the authorization token used to authorize incoming webhook requests. + * + * @return string + */ + public abstract function getAuthorization(); + + /** + * Receives the JSON body sent from Top.gg containing webhook event information. + * + * @param array $data The JSON body sent from Top.gg containing webhook event information. + * @return void + */ + public abstract function callback(array $data); +} + +?> \ No newline at end of file diff --git a/src/TopPHP/Widget.php b/src/TopPHP/Widget.php index 07f2e83..6a83305 100644 --- a/src/TopPHP/Widget.php +++ b/src/TopPHP/Widget.php @@ -1,5 +1,15 @@ Date: Fri, 10 Oct 2025 15:04:43 +0700 Subject: [PATCH 15/21] [doc,fix]: minor documentation tweaks and make use of bearer token prefix --- src/TopPHP/API/Request.php | 6 +++--- src/TopPHP/DBL.php | 6 +++--- src/TopPHP/Widget.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/TopPHP/API/Request.php b/src/TopPHP/API/Request.php index f32ddd9..7aef83e 100644 --- a/src/TopPHP/API/Request.php +++ b/src/TopPHP/API/Request.php @@ -38,7 +38,7 @@ class Request implements RequestStruct /** @var string */ private $response; - public const SERVER_ADDR = "https://top.gg/api/v1"; + public const SERVER_ADDR = "https://top.gg/api"; public const SERVER_PORT = 80; /** @@ -91,7 +91,7 @@ public function req(string $type, ?string $path = null, array $json = [], int $p "http" => [ "method" => $type, "header" => "Content-Type: application/json" . "\r\n" . - "Authorization: {$this->token}" . "\r\n" + "Authorization: Bearer {$this->token}" . "\r\n" ] ]; @@ -134,7 +134,7 @@ public function req(string $type, ?string $path = null, array $json = [], int $p "type" => $type, "path" => $_path, "status" => $_response, - "json" => ["message" => $_error["message"]] + "json" => ["message" => $_error["message"] ?? $_error["detail"]] ]; return $this->content; diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 8085671..0025045 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -231,7 +231,7 @@ public function get_bot(int $id): array } /** - * Returns the unique voters of the bot. + * Returns the unique voters of the project. * * @param int $page The page counter. Defaults to 1. * @return array @@ -242,9 +242,9 @@ public function get_voters(int $page = 1): array } /** - * Returns a boolean for if a user has voted for your bot. + * Returns a boolean for if a user has voted for your project. * - * @param int $user The user Snowflake ID. + * @param int $user The user ID. * @return array */ public function has_voted(int $user): array diff --git a/src/TopPHP/Widget.php b/src/TopPHP/Widget.php index 6a83305..1582983 100644 --- a/src/TopPHP/Widget.php +++ b/src/TopPHP/Widget.php @@ -43,7 +43,7 @@ public static function votes(WidgetType $ty, int $id): string { } /** - * Generates a small widget URL for displaying an entity's owner. + * Generates a small widget URL for displaying a project's owner. * * @param WidgetType $ty The widget type. * @param int $id The ID. From d185440764d58fad7368e628ee371a25d07dba5d Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 15:22:58 +0700 Subject: [PATCH 16/21] revert: revert breaking changes --- src/TopPHP/DBL.php | 44 +++++++++++++++---------------- src/TopPHP/Structs/BaseStruct.php | 8 +++--- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 0025045..09eccac 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -163,7 +163,7 @@ private function check_auto_stats(string $url, callable $callback) { try { - $this->post_server_count($callback()); + $this->post_stats($callback()); } catch (\Exception $error) { echo $error; } finally @@ -231,12 +231,13 @@ public function get_bot(int $id): array } /** - * Returns the unique voters of the project. + * Returns the unique voters of your project. * + * @param int $id The project ID. Unused, no longer has an effect. * @param int $page The page counter. Defaults to 1. * @return array */ - public function get_voters(int $page = 1): array + public function get_votes(int $id, int $page = 1): array { return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } @@ -244,48 +245,45 @@ public function get_voters(int $page = 1): array /** * Returns a boolean for if a user has voted for your project. * + * @param int $id The project ID. Unused, no longer has an effect. * @param int $user The user ID. * @return array */ - public function has_voted(int $user): array + public function get_user_vote(int $id, int $user): array { - return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]; + return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"]; } /** - * Returns a boolean for if the weekend multiplier is active, where a single vote counts as two. + * Returns your bot's posted statistics. * - * @return array + * @param int $id The bot ID. Unused, no longer has an effect. + * @return array */ - public function is_weekend(): array + public function get_stats(int $id = 0): array { - return $this->api->req("GET", "/weekend")["json"]; + return $this->api->req("GET", "/bots/stats")["json"]; } /** - * Returns your bot's posted server count. + * Posts your Discord bot's statistics to the API. This will update the server count in your Discord bot's Top.gg page. * - * @return int + * @param int $id The bot ID. Unused, no longer has an effect. + * @param array $json Your bot's new statistics. */ - public function get_server_count(): int + public function post_stats(int $id, array $json) { - return $this->api->req("GET", "/bots/stats")["json"]["server_count"]; + $this->api->req("POST", "/bots/stats", $json); } /** - * Posts your bot's server count to Top.gg. + * Returns a boolean for if the weekend multiplier is active, where a single vote counts as two. * - * @param int $server_count Your bot's server count. + * @return array */ - public function post_server_count(int $server_count) + public function is_weekend(): array { - if (!$server_count || $server_count < 0) { - throw new \Exception("Server count must not be null, zero, or less."); - } - - $this->api->req("POST", "/bots/stats", [ - "server_count" => $server_count, - ]); + return $this->api->req("GET", "/weekend")["json"]; } /** diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index dc1d7cc..a4d67f3 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -26,16 +26,16 @@ public function get_bots(int $limit, int $offset, string $sort_by); public function get_bot(int $id); /** Get information on your voters, vote check, weekend multiplier, and stats. */ - public function get_voters(int $page); - public function has_voted(int $user); + public function get_votes(int $id, int $page); + public function get_user_vote(int $id, int $user); public function is_weekend(); - public function get_server_count(); + public function get_stats(int $id); /** * POST requests will be handled here, and have to be * taken into account differently due to their nature. */ - public function post_server_count(int $server_count); + public function post_stats(int $id, array $json); /** Accessor methods for private instances. */ public function getHttp(); From a763dec0f3b1e32a490e728aa4fda0d8b8177cbe Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 16:03:22 +0700 Subject: [PATCH 17/21] revert: revert deletion of methods, instead just deprecate them --- src/TopPHP/API/Http.php | 1 + src/TopPHP/DBL.php | 52 +++++++++++++++++++++++++++++++ src/TopPHP/Structs/BaseStruct.php | 3 ++ 3 files changed, 56 insertions(+) diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index d46c800..8d893d1 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -24,6 +24,7 @@ class Http implements HttpStruct { public const BOT = "bots"; + public const USER = "users"; public const POST = "POST"; public const GET = "GET"; diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 09eccac..2ed785d 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -186,6 +186,58 @@ protected function check_safety() if ($this->features["safety"]) die(); } + /** + * @deprecated Use get_bots() instead. + * + * Shows the information from the specified type through a query search. + * + * @param string $type The search type. + * @param array $json The JSON query fields, with key:val as assoc. + * @return array + */ + public function show_info(string $type, array $json = []): array + { + trigger_error('show_info() is deprecated, use get_bots() instead', E_USER_DEPRECATED); + + switch($type) + { + case Http::BOT: + break; + + default: + die("Invalid search parameter: {$type}"); + break; + } + + return $this->api->req("GET", "/bots", $json)["json"]; + } + + /** + * @deprecated Use get_bot() instead. + * + * Displays the general information about something given through the search type. + * + * @param string $type The search type. + * @param int $id The bot/user ID. + * @return array + */ + public function find_info(string $type, int $id): array + { + trigger_error('find_info() is deprecated, use get_bot() instead', E_USER_DEPRECATED); + + switch($type) + { + case Http::BOT: + break; + + default: + die("Invalid search parameter: {$type}"); + break; + } + + return $this->api->req("GET", "/bots/{$id}")["json"]; + } + /** * Displays the general information of several bots. * diff --git a/src/TopPHP/Structs/BaseStruct.php b/src/TopPHP/Structs/BaseStruct.php index a4d67f3..c5dca64 100644 --- a/src/TopPHP/Structs/BaseStruct.php +++ b/src/TopPHP/Structs/BaseStruct.php @@ -22,6 +22,9 @@ public function __construct(array $parameters); * procedures. */ /** Show statistics for all bots/users or specified. */ + public function show_info(string $type, array $json = []); + public function find_info(string $type, int $id); + public function get_bots(int $limit, int $offset, string $sort_by); public function get_bot(int $id); From fb3c722dddd69c46069e1fd89c671552396352ab Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 16:08:56 +0700 Subject: [PATCH 18/21] revert: move method declarations to help with diff readability --- src/TopPHP/DBL.php | 88 +++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 2ed785d..4338081 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -238,50 +238,6 @@ public function find_info(string $type, int $id): array return $this->api->req("GET", "/bots/{$id}")["json"]; } - /** - * Displays the general information of several bots. - * - * @param int $limit The maximum amount of bots to be queried. - * @param int $offset The amount of bots to be skipped. - * @param string $sort_by Sorts results based on a specific criteria. Results will always be descending. - * @return array - */ - public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array - { - if ($limit <= 0) { - $limit .= 1; - } else if ($limit > 500) { - $limit .= 500; - } - - if ($offset < 0) { - $offset .= 0; - } else if ($offset > 499) { - $offset .= 499; - } - - if ($sort_by !== "monthlyPoints" && $sort_by !== "date" && $sort_by !== "id") { - throw new \Exception("sort_by argument must be \"monthlyPoints\", \"date\", or \"id\"."); - } - - return $this->api->req("GET", "/bots", [ - "limit" => $limit, - "offset" => $offset, - "sort" => $sort_by, - ])["json"]; - } - - /** - * Displays the general information about a bot. - * - * @param int $id The bot ID. - * @return array - */ - public function get_bot(int $id): array - { - return $this->api->req("GET", "/bots/{$id}")["json"]; - } - /** * Returns the unique voters of your project. * @@ -328,6 +284,50 @@ public function post_stats(int $id, array $json) $this->api->req("POST", "/bots/stats", $json); } + /** + * Displays the general information of several bots. + * + * @param int $limit The maximum amount of bots to be queried. + * @param int $offset The amount of bots to be skipped. + * @param string $sort_by Sorts results based on a specific criteria. Results will always be descending. + * @return array + */ + public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "monthlyPoints"): array + { + if ($limit <= 0) { + $limit .= 1; + } else if ($limit > 500) { + $limit .= 500; + } + + if ($offset < 0) { + $offset .= 0; + } else if ($offset > 499) { + $offset .= 499; + } + + if ($sort_by !== "monthlyPoints" && $sort_by !== "date" && $sort_by !== "id") { + throw new \Exception("sort_by argument must be \"monthlyPoints\", \"date\", or \"id\"."); + } + + return $this->api->req("GET", "/bots", [ + "limit" => $limit, + "offset" => $offset, + "sort" => $sort_by, + ])["json"]; + } + + /** + * Displays the general information about a bot. + * + * @param int $id The bot ID. + * @return array + */ + public function get_bot(int $id): array + { + return $this->api->req("GET", "/bots/{$id}")["json"]; + } + /** * Returns a boolean for if the weekend multiplier is active, where a single vote counts as two. * From 92ccb8a2f9733b9371acf55025ce63620887ec94 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 16:11:47 +0700 Subject: [PATCH 19/21] refactor: throw an Exception instead of die --- src/TopPHP/DBL.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 4338081..84df082 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -205,7 +205,7 @@ public function show_info(string $type, array $json = []): array break; default: - die("Invalid search parameter: {$type}"); + throw new \Exception("Invalid search parameter: {$type}"); break; } @@ -231,7 +231,7 @@ public function find_info(string $type, int $id): array break; default: - die("Invalid search parameter: {$type}"); + throw new \Exception("Invalid search parameter: {$type}"); break; } From 820a342e06592dbd0d10b32b1464506483dbb4bf Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 17:33:11 +0700 Subject: [PATCH 20/21] feat: adapt to v1 --- README.md | 123 +++++++++++++----- main.php | 55 +++++++- .../Exceptions/GlobalRatelimitException.php | 51 -------- .../API/Exceptions/MissingStatsException.php | 52 -------- .../API/Exceptions/MissingTokenException.php | 23 +--- .../Exceptions/ResourceRatelimitException.php | 22 +--- src/TopPHP/API/Http.php | 3 +- src/TopPHP/DBL.php | 39 +++--- src/TopPHP/V1DBL.php | 56 ++++++++ 9 files changed, 229 insertions(+), 195 deletions(-) delete mode 100644 src/TopPHP/API/Exceptions/GlobalRatelimitException.php delete mode 100644 src/TopPHP/API/Exceptions/MissingStatsException.php create mode 100644 src/TopPHP/V1DBL.php diff --git a/README.md b/README.md index 7538c08..8f1b76a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,27 @@ The community-maintained PHP library for Top.gg. +## Chapters + +- [Installation](#installation) +- [Setting up](#setting-up) +- [Usage](#usage) + - [API v1](#api-v1) + - [Getting your project's vote information of a user](#getting-your-projects-vote-information-of-a-user) + - [Posting your bot's application commands list](#posting-your-bots-application-commands-list) + - [API v0](#api-v0) + - [Getting a bot](#getting-a-bot) + - [Getting several bots](#getting-several-bots) + - [Getting your project's voters](#getting-your-projects-voters) + - [Check if a user has voted for your project](#check-if-a-user-has-voted-for-your-project) + - [Getting your bot's statistics](#getting-your-bots-statistics) + - [Posting your bot's statistics](#posting-your-bots-statistics) + - [Automatically posting your bot's statistics every few minutes](#automatically-posting-your-bots-statistics-every-few-minutes) + - [Checking if the weekend vote multiplier is active](#checking-if-the-weekend-vote-multiplier-is-active) + - [Generating widget URLs](#generating-widget-urls) + - [Webhooks](#webhooks) + - [Being notified whenever someone voted for your project](#being-notified-whenever-someone-voted-for-your-project) + ## Installation ```sh @@ -10,74 +31,116 @@ $ composer require top-gg/php-sdk ## Setting up +### API v1 + +> **NOTE**: API v1 also includes API v0. + +```php +include_once __DIR__ . "/vendor/autoload.php"; + +use DBL\V1DBL; + +$client = new V1DBL([ + "token" => "Top.gg API token" +]); +``` + +### API v0 + ```php include_once __DIR__ . "/vendor/autoload.php"; use DBL\DBL; $client = new DBL([ - "token" => "Insert your Top.gg API token here." + "token" => "Top.gg API token" ]); ``` ## Usage -### Getting a bot +### API v1 + +#### Getting your project's vote information of a user ```php -$bot = $client->get_bot(); +$vote = $client->get_vote(661200758510977084); ``` -### Getting several bots +#### Posting your bot's application commands list -#### With defaults +```php +$client->post_commands([ + [ + "options" => [], + "name" => "test", + "name_localizations" => null, + "description" => "command description", + "description_localizations" => null, + "contexts" => [], + "default_permission" => null, + "default_member_permissions" => null, + "dm_permission" => false, + "integration_types" => [], + "nsfw" => false + ] +]); +``` + +### API v0 + +#### Getting a bot ```php -$bots = $client->get_bots(); +$bot = $client->get_bot(1026525568344264724); ``` -#### With explicit arguments +#### Getting several bots ```php // Limit Offset Sort by -$bots = $client->get_bots(50, 0, "date"); +$bots = $client->get_bots(50, 0, "monthlyPoints"); ``` -### Getting your bot's voters +#### Getting your project's voters -#### First page +##### First page ```php -$voters = $client->get_voters(); +$voters = $client->get_votes(); ``` -#### Subsequent pages +##### Subsequent pages ```php -$voters = $client->get_voters(2); +// Bot ID (unused) Page number +$voters = $client->get_votes(0, 2); ``` -### Check if a user has voted for your bot +#### Check if a user has voted for your project ```php -$has_voted = $client->has_voted(205680187394752512); +// Bot ID (unused) User ID +$has_voted = $client->get_user_vote(0, 661200758510977084); ``` -### Getting your bot's server count +#### Getting your bot's statistics ```php -$server_count = $client->get_server_count(); +$stats = $client->get_stats(); ``` -### Posting your bot's server count +#### Posting your bot's statistics ```php -$client->post_server_count($bot->get_server_count()); +$client->post_stats(0, [ + "server_count" => $bot->get_server_count() +]); ``` -### Automatically posting your bot's server count every few minutes +#### Automatically posting your bot's statistics every few minutes -> **NOTE:** Considering PHP's shortcomings, this is only possible via a URL. +> **NOTE**: Considering PHP's shortcomings, this is only possible via a URL. In your original client declaration: @@ -87,21 +150,23 @@ $client = new DBL([ "auto_stats" => [ "url": "Your URL", "callback": => function () use ($bot) { - return $bot->get_server_count(); + return [ + "server_count" => $bot->get_server_count() + ]; } ] ]); ``` -### Checking if the weekend vote multiplier is active +#### Checking if the weekend vote multiplier is active ```php $is_weekend = $client->is_weekend(); ``` -### Generating widget URLs +#### Generating widget URLs -#### Large +##### Large ```php use DBL\Widget; @@ -110,7 +175,7 @@ use DBL\WidgetType; $widget_url = Widget::large(WidgetType::DiscordBot, 574652751745777665); ``` -#### Votes +##### Votes ```php use DBL\Widget; @@ -119,7 +184,7 @@ use DBL\WidgetType; $widget_url = Widget::votes(WidgetType::DiscordBot, 574652751745777665); ``` -#### Owner +##### Owner ```php use DBL\Widget; @@ -128,7 +193,7 @@ use DBL\WidgetType; $widget_url = Widget::owner(WidgetType::DiscordBot, 574652751745777665); ``` -#### Social +##### Social ```php use DBL\Widget; @@ -139,7 +204,7 @@ $widget_url = Widget::social(WidgetType::DiscordBot, 574652751745777665); ### Webhooks -#### Being notified whenever someone voted for your bot +#### Being notified whenever someone voted for your project **With Laravel:** diff --git a/main.php b/main.php index ab78619..395f293 100644 --- a/main.php +++ b/main.php @@ -18,12 +18,61 @@ */ include_once __DIR__ . "/vendor/autoload.php"; -use DBL\DBL; -use DBL\API\Http; +use DBL\V1DBL; $token = @file_get_contents(".TOKEN"); -$api = new DBL([ +$client = new V1DBL([ "token" => $token ]); +echo "\nrunning get bot:\n"; +$bot = $client->get_bot(1026525568344264724); +print_r($bot); + +echo "\nrunning get bots:\n"; +$bots = $client->get_bots(); +print_r($bots); + +echo "\nrunning get votes:\n"; +$voters = $client->get_votes(); +print_r($voters); + +echo "\nrunning get user vote:\n"; +$has_voted = $client->get_user_vote(0, 661200758510977084); +print_r($has_voted); + +echo "\nrunning get stats:\n"; +$stats = $client->get_stats(); +print_r($stats); + +echo "\nrunning post stats:\n"; +$client->post_stats(0, [ + "server_count" => 2 +]); + +echo "\nrunning is weekend:\n"; +$is_weekend = $client->is_weekend(); +print_r($is_weekend); + +echo "\nrunning post commands:\n"; +$client->post_commands([ + [ + "options" => [], + "name" => "test", + "name_localizations" => null, + "description" => "command description", + "description_localizations" => null, + "contexts" => [], + "default_permission" => null, + "default_member_permissions" => null, + "dm_permission" => false, + "integration_types" => [], + "nsfw" => false + ] +]); + +echo "\nrunning get vote:\n"; +$vote = $client->get_vote(661200758510977084); +print_r($vote); + ?> diff --git a/src/TopPHP/API/Exceptions/GlobalRatelimitException.php b/src/TopPHP/API/Exceptions/GlobalRatelimitException.php deleted file mode 100644 index b22e98b..0000000 --- a/src/TopPHP/API/Exceptions/GlobalRatelimitException.php +++ /dev/null @@ -1,51 +0,0 @@ -message = "You have encountered a global ratelimit. Please refer to the JSON contents for your remaining time."; - - switch($type) - { - case self::THROW_NONE: - break; - - default: - die($this->message); - break; - } - } -} - -?> diff --git a/src/TopPHP/API/Exceptions/MissingStatsException.php b/src/TopPHP/API/Exceptions/MissingStatsException.php deleted file mode 100644 index 58d6237..0000000 --- a/src/TopPHP/API/Exceptions/MissingStatsException.php +++ /dev/null @@ -1,52 +0,0 @@ -message = "The API could not make a successful connection due to missing value(s). (Check for valid value?)"; - - switch($type) - { - case self::THROW_NONE: - break; - - default: - die($this->message); - break; - } - } -} - -?> diff --git a/src/TopPHP/API/Exceptions/MissingTokenException.php b/src/TopPHP/API/Exceptions/MissingTokenException.php index 194f7ac..7cbbade 100644 --- a/src/TopPHP/API/Exceptions/MissingTokenException.php +++ b/src/TopPHP/API/Exceptions/MissingTokenException.php @@ -17,34 +17,19 @@ * This allows for an exception to be made when * the DBL class does not detect a token. */ -class MissingTokenException +class MissingTokenException extends \Exception { /** @var mixed */ public $message; - /** Special throwing rules. */ - public const THROW_NONE = 0; - public const THROW_DEFAULT = 1; - /** * Creates a MissingTokenException class. - * - * @param const|null $type The throwing type. - * @return void */ - public function __construct($type = self::THROW_DEFAULT) + public function __construct() { $this->message = "The API could not make a successful connection due to a missing token. (Do you have a token path specified in the DBL class?)"; - - switch($type) - { - case self::THROW_NONE: - break; - - default: - die($this->message); - break; - } + + parent::__construct($this->message); } } diff --git a/src/TopPHP/API/Exceptions/ResourceRatelimitException.php b/src/TopPHP/API/Exceptions/ResourceRatelimitException.php index 7bde38d..1465c6a 100644 --- a/src/TopPHP/API/Exceptions/ResourceRatelimitException.php +++ b/src/TopPHP/API/Exceptions/ResourceRatelimitException.php @@ -17,35 +17,21 @@ * This allows for exceptions to be made when * the HTTP hits a rate limit for a specific request. */ -class ResourceRatelimitException +class ResourceRatelimitException extends \Exception { /** @var mixed */ public $message; - /** Special throwing rules. */ - public const THROW_NONE = 0; - public const THROW_DEFAULT = 1; - /** * Creates a ResourceRatelimitException class. * * @param string $message The error message. - * @param const|null $type The throwing type. - * @return void */ - public function __construct(string $message, $type = self::THROW_DEFAULT) + public function __construct(string $message) { - $this->message = $message; + parent::__construct($message); - switch($type) - { - case self::THROW_NONE: - break; - - default: - die($this->message); - break; - } + $this->message = $message; } } diff --git a/src/TopPHP/API/Http.php b/src/TopPHP/API/Http.php index 8d893d1..3cf1b23 100644 --- a/src/TopPHP/API/Http.php +++ b/src/TopPHP/API/Http.php @@ -13,6 +13,7 @@ namespace DBL\API; use DBL\Structs\HttpStruct; +use DBL\API\Exceptions\ResourceRatelimitException; /** * Represents the HTTP class for Top.gg. @@ -104,7 +105,7 @@ public function call(string $type, string $path, array $payload = []): array * will be updated in the future. */ - die("You have encountered a rate limit. Please refer to the JSON contents for the remaining time."); + throw new ResourceRatelimitException("You have encountered a rate limit. Please refer to the JSON contents for the remaining time."); } /** Now provide the information for the structure. */ diff --git a/src/TopPHP/DBL.php b/src/TopPHP/DBL.php index 84df082..dd0bbf2 100644 --- a/src/TopPHP/DBL.php +++ b/src/TopPHP/DBL.php @@ -15,19 +15,14 @@ use DBL\API\Http; use DBL\API\Request; use DBL\API\Exceptions\MissingTokenException; -use DBL\API\Exceptions\MissingStatsException; use DBL\Structs\BaseStruct; use DBL\Webhook; use DBL\Widget; /** - * Represents the TopPHP/Top.gg base class. - * This class handles all of the specified - * GET and POST requests that the API allows - * to be called on, and has methods declared - * for each specific/particular usage. + * Top.gg API v0 client */ -final class DBL implements BaseStruct +class DBL implements BaseStruct { /** * @var string @@ -156,14 +151,14 @@ public function __construct(array $parameters) * This can only be done for a website URL. * * @param string $url The HTTP path you're using. - * @param callable $callback The callback function that returns the bot's server count. + * @param callable $callback The callback function that returns the bot's statistics. * @return void */ private function check_auto_stats(string $url, callable $callback) { try { - $this->post_stats($callback()); + $this->post_stats(0, $callback()); } catch (\Exception $error) { echo $error; } finally @@ -215,7 +210,7 @@ public function show_info(string $type, array $json = []): array /** * @deprecated Use get_bot() instead. * - * Displays the general information about something given through the search type. + * Gets the general information about something given through the search type. * * @param string $type The search type. * @param int $id The bot/user ID. @@ -245,21 +240,21 @@ public function find_info(string $type, int $id): array * @param int $page The page counter. Defaults to 1. * @return array */ - public function get_votes(int $id, int $page = 1): array + public function get_votes(int $id = 0, int $page = 1): array { return $this->api->req("GET", "/bots/{$this->id}/votes", ["page" => $page])["json"]; } /** - * Returns a boolean for if a user has voted for your project. + * Returns true if a user has voted for your project. * * @param int $id The project ID. Unused, no longer has an effect. * @param int $user The user ID. - * @return array + * @return bool */ - public function get_user_vote(int $id, int $user): array + public function get_user_vote(int $id, int $user): bool { - return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"]; + return $this->api->req("GET", "/bots/check", ["userId" => $user])["json"]["voted"] != 0; } /** @@ -274,7 +269,7 @@ public function get_stats(int $id = 0): array } /** - * Posts your Discord bot's statistics to the API. This will update the server count in your Discord bot's Top.gg page. + * Posts your Discord bot's statistics to the API. This will update the statistics in your Discord bot's Top.gg page. * * @param int $id The bot ID. Unused, no longer has an effect. * @param array $json Your bot's new statistics. @@ -285,7 +280,7 @@ public function post_stats(int $id, array $json) } /** - * Displays the general information of several bots. + * Gets the general information of several bots. * * @param int $limit The maximum amount of bots to be queried. * @param int $offset The amount of bots to be skipped. @@ -318,7 +313,7 @@ public function get_bots(int $limit = 50, int $offset = 0, string $sort_by = "mo } /** - * Displays the general information about a bot. + * Gets the general information about a bot. * * @param int $id The bot ID. * @return array @@ -329,13 +324,13 @@ public function get_bot(int $id): array } /** - * Returns a boolean for if the weekend multiplier is active, where a single vote counts as two. + * Returns true if the weekend multiplier is active, where a single vote counts as two. * - * @return array + * @return bool */ - public function is_weekend(): array + public function is_weekend(): bool { - return $this->api->req("GET", "/weekend")["json"]; + return $this->api->req("GET", "/weekend")["json"]["is_weekend"]; } /** diff --git a/src/TopPHP/V1DBL.php b/src/TopPHP/V1DBL.php new file mode 100644 index 0000000..9cdba6b --- /dev/null +++ b/src/TopPHP/V1DBL.php @@ -0,0 +1,56 @@ +api->req("POST", "/v1/projects/@me/commands", $commands); + } + + /** + * Gets the latest vote information of a Top.gg user on your project. + * + * @param int $id The user's ID. + * @param string $source The ID type to use. Defaults to "discord". + * @return array|null + */ + public function get_vote(int $id, string $source = "discord"): array|null + { + if ($source !== "topgg" && $source !== "discord") + { + throw new \Exception("source argument must be \"topgg\" or \"discord\"."); + } + + $result = $this->api->req("GET", "/v1/projects/@me/votes/{$id}", ["source" => $source]); + + if ($result["status"] === "404") { + return null; + } + + return $result["json"]; + } +} + +?> From 7f346209f25fb2a879767046bb0f904d1f5de513 Mon Sep 17 00:00:00 2001 From: null <60427892+null8626@users.noreply.github.com> Date: Tue, 21 Oct 2025 00:07:59 +0700 Subject: [PATCH 21/21] doc: fix API version links in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8f1b76a..17f6513 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ The community-maintained PHP library for Top.gg. - [Installation](#installation) - [Setting up](#setting-up) - [Usage](#usage) - - [API v1](#api-v1) + - [API v1](#api-v1-1) - [Getting your project's vote information of a user](#getting-your-projects-vote-information-of-a-user) - [Posting your bot's application commands list](#posting-your-bots-application-commands-list) - - [API v0](#api-v0) + - [API v0](#api-v0-1) - [Getting a bot](#getting-a-bot) - [Getting several bots](#getting-several-bots) - [Getting your project's voters](#getting-your-projects-voters) @@ -239,4 +239,4 @@ class MyVoteListener extends Webhook { } Route::post('/votes', [MyVoteListener::class, "main"]); -``` \ No newline at end of file +```