├── .gitattributes ├── composer.phar ├── .gitignore ├── .idea ├── vcs.xml ├── .gitignore ├── modules.xml ├── TopPHP.iml └── php.xml ├── composer.json ├── src └── TopPHP │ ├── Structs │ ├── HttpStruct.php │ ├── RequestStruct.php │ └── BaseStruct.php │ ├── API │ ├── Exceptions │ │ ├── MissingTokenException.php │ │ ├── ResourceRatelimitException.php │ │ ├── GlobalRatelimitException.php │ │ └── MissingStatsException.php │ ├── Http.php │ └── Request.php │ └── DBL.php ├── README.md ├── main.php └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Top-gg-Community/php-sdk/HEAD/composer.phar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # composer 2 | /vendor 3 | composer.lock 4 | 5 | # regular files 6 | main.php 7 | .TOKEN 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "top-gg/php-sdk", 3 | "description": "The official Top.gg PHP API wrapper.", 4 | "license": "MIT", 5 | "require": { 6 | "php": "^7.3|^8.0" 7 | }, 8 | "authors": [ 9 | { 10 | "name": "James Walston", 11 | "email": "james@digicale.com" 12 | } 13 | ], 14 | "autoload": { 15 | "psr-4": {"DBL\\": "src/TopPHP/"} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.idea/TopPHP.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/TopPHP/Structs/HttpStruct.php: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TopPHP 2 | A Top.gg API wrapper written in PHP 8. 3 | 4 | ## Documentation 5 | See [here](https://docs.top.gg/libraries/php/) for the official information. 6 | 7 | ## Installation 8 | TopPHP uses composer to download. In order to install the library, use the following line: 9 | 10 | `composer require top-gg/php-sdk` 11 | 12 | ## Features 13 | 14 | * Working GET and POST requests. 15 | * Enumerable constants for HTTP search lookups. 16 | * Flexible namespaces and interfaces for easily editing. 17 | * Up-to-standard package following the latest PSR. 18 | * Automatic bot statistics POST requests. (Shards, guilds) 19 | 20 | ## Coming Soon 21 | 22 | * Webhooks 23 | * Forced library global rate-limiting. 24 | -------------------------------------------------------------------------------- /main.php: -------------------------------------------------------------------------------- 1 | $token 27 | ]); 28 | 29 | ?> 30 | -------------------------------------------------------------------------------- /src/TopPHP/Structs/RequestStruct.php: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-present fl0w & Top.gg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/TopPHP/API/Exceptions/MissingTokenException.php: -------------------------------------------------------------------------------- 1 | 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?)"; 38 | 39 | switch($type) 40 | { 41 | case self::THROW_NONE: 42 | break; 43 | 44 | default: 45 | die($this->message); 46 | break; 47 | } 48 | } 49 | } 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /src/TopPHP/API/Exceptions/ResourceRatelimitException.php: -------------------------------------------------------------------------------- 1 | message = $message; 39 | 40 | switch($type) 41 | { 42 | case self::THROW_NONE: 43 | break; 44 | 45 | default: 46 | die($this->message); 47 | break; 48 | } 49 | } 50 | } 51 | 52 | ?> 53 | -------------------------------------------------------------------------------- /src/TopPHP/API/Exceptions/GlobalRatelimitException.php: -------------------------------------------------------------------------------- 1 | message = "You have encountered a global ratelimit. Please refer to the JSON contents for your remaining time."; 38 | 39 | switch($type) 40 | { 41 | case self::THROW_NONE: 42 | break; 43 | 44 | default: 45 | die($this->message); 46 | break; 47 | } 48 | } 49 | } 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /src/TopPHP/API/Exceptions/MissingStatsException.php: -------------------------------------------------------------------------------- 1 | message = "The API could not make a successful connection due to missing value(s). (Check for valid value?)"; 39 | 40 | switch($type) 41 | { 42 | case self::THROW_NONE: 43 | break; 44 | 45 | default: 46 | die($this->message); 47 | break; 48 | } 49 | } 50 | } 51 | 52 | ?> 53 | -------------------------------------------------------------------------------- /src/TopPHP/Structs/BaseStruct.php: -------------------------------------------------------------------------------- 1 | 48 | -------------------------------------------------------------------------------- /src/TopPHP/API/Http.php: -------------------------------------------------------------------------------- 1 | http = $http; 46 | $this->port = $port; 47 | } 48 | 49 | /** 50 | * Calls the HTTP path with a specified request. 51 | * Has to meet with the constants of currently 52 | * accepted HTTP requests compatible with the API. 53 | * 54 | * @param string $type The HTTP request you're using. 55 | * @param string $path The HTTP path you're calling. 56 | * @param array $payload Additional information you want to pass on as JSON. 57 | * @return array 58 | */ 59 | public function call(string $type, string $path, array $payload = []): array 60 | { 61 | /** 62 | * Determine the type of call in a temporary 63 | * variable to later pass on as information. 64 | * (PHP 8+ method commented below.) 65 | */ 66 | switch($type) 67 | { 68 | case self::POST: 69 | $_type = "POST"; 70 | break; 71 | 72 | case self::GET: 73 | $_type = "GET"; 74 | break; 75 | 76 | default: 77 | $_type = null; 78 | break; 79 | } 80 | 81 | /* 82 | $_type = match($type) 83 | { 84 | Type\RequestType::POST => "POST", 85 | Type\RequestType::GET => "GET", 86 | "default" => null 87 | }; 88 | */ 89 | 90 | /** Determine what our response status code is. */ 91 | $_headers = ($_type) ? get_headers($path) : "400"; 92 | $_response = substr($_headers[0], 9, 3); 93 | 94 | if($_response === "401") $_response = "200"; // This is because the token is not being enforced. 95 | if($_response === "429") 96 | { 97 | /** 98 | * We have two specific ratelimit exceptions here. 99 | * To determine this, the content has to be read 100 | * in order to give the right exception. 101 | * 102 | * For now we'll give a standard Exception, this 103 | * will be updated in the future. 104 | */ 105 | 106 | die("You have encountered a rate limit. Please refer to the JSON contents for the remaining time."); 107 | } 108 | 109 | /** Now provide the information for the structure. */ 110 | $_path = ($_response === "200") ? $path : null; 111 | $_payload = (!$payload) ? $payload : null; 112 | 113 | /** 114 | * All returned information will be formatted this way. 115 | * This will make grabbing argument values easier 116 | * when handling the HTTP requests. 117 | */ 118 | return 119 | [ 120 | "type" => $_type, 121 | "path" => $_path, 122 | "status" => $_response, 123 | "json" => $_payload 124 | ]; 125 | } 126 | 127 | /** 128 | * Gets the HTTP address. 129 | * 130 | * @return string 131 | */ 132 | public function getHttp(): string 133 | { 134 | return $this->http; 135 | } 136 | 137 | /** 138 | * Gets the HTTP communication endpoint. 139 | * 140 | * @return int 141 | */ 142 | public function getPort(): int 143 | { 144 | return $this->port; 145 | } 146 | } 147 | 148 | ?> 149 | -------------------------------------------------------------------------------- /src/TopPHP/API/Request.php: -------------------------------------------------------------------------------- 1 | http = $http; 53 | $this->token = $token; 54 | $this->content = []; 55 | $this->cache = null; 56 | $this->response = null; 57 | } 58 | 59 | /** 60 | * Defines how an HTTP request is inferred on. 61 | * The rule is simple: as long as a URL/URI path 62 | * is given and the response is OK, and path is said 63 | * to be valid, a request will be validated. Otherwise, 64 | * an exception is thrown. 65 | * 66 | * @param string $type The HTTP request you're using. 67 | * @param string $path The HTTP path you're calling. 68 | * @param string $resp An HTTP response to be given when handshake is successful. 69 | * @param int $port The HTTP port you're inferring. 70 | * @param array $json Additional information you want to pass on as JSON. 71 | * @return array 72 | */ 73 | public function req(string $type, string $path = null, array $json = [], int $port = self::SERVER_PORT): array 74 | { 75 | $_http = new Http($this->http, $port); 76 | $_path = ($path) ? $_http->getHttp(), $path : null; 77 | $_error = false; 78 | $_request = null; 79 | $_response = null; 80 | $_json = (![]) ? http_build_query($json) : null; 81 | 82 | try 83 | { 84 | /** Ensure headers are restored. */ 85 | // header_remove("Content-Type"); 86 | 87 | /** 88 | * Set up the HTTP request structure. 89 | * Will contextualize and create how we will interact. 90 | */ 91 | $_path = $_path, $_json; 92 | $_struct = [ 93 | "http" => [ 94 | "method" => $type, 95 | "header" => "Content-Type: application/json" . "\r\n" . 96 | "Authorization: {$this->token}" . "\r\n" 97 | ] 98 | ]; 99 | $_struct = @stream_context_create($_struct); 100 | 101 | /** 102 | * Here is where the official request is made 103 | * to receive information. 104 | */ 105 | $_request = @file_get_contents($_path, true, $_struct); 106 | if(!$_request) $_error = true; 107 | } 108 | 109 | catch (Exception $error) { return $error; } 110 | 111 | finally 112 | { 113 | if(!$_error) 114 | { 115 | // header("Content-Type: application/json"); 116 | // @http_response_code(intval($this->response) + 0); 117 | 118 | $_struct = $_http->call( 119 | $type, 120 | $_path, 121 | json_decode($_request, true) 122 | ); 123 | $this->cache = $_struct; 124 | 125 | return $_struct; 126 | } 127 | 128 | else 129 | { 130 | error_reporting(E_ALL); 131 | $_error = error_get_last(); 132 | 133 | /** 134 | * We'll need to manually pull the response 135 | * status code for this when the error comes. 136 | */ 137 | $_headers = get_headers($_path); 138 | $this->response = $_response = substr($_headers[0], 9, 3); 139 | 140 | $this->content = 141 | [ 142 | "type" => $type, 143 | "path" => $_path, 144 | "status" => $_response, 145 | "json" => ["message" => $_error["message"]] 146 | ]; 147 | 148 | return $this->content; 149 | } 150 | } 151 | } 152 | 153 | /** 154 | * Gets the HTTP webpage's contents. 155 | * 156 | * @return array 157 | */ 158 | public function getContents(): array 159 | { 160 | return $this->content; 161 | } 162 | 163 | /** 164 | * Gets the cache of the last requested interaction. 165 | * It is recommended to save this value into an 166 | * instance when being used for preservation. 167 | * 168 | * @return string 169 | */ 170 | public function getCache(): string 171 | { 172 | return $this->cache; 173 | } 174 | 175 | /** 176 | * Gets the HTTP response status. 177 | * 178 | * @return string 179 | */ 180 | public function getResponse(): string 181 | { 182 | return $this->response; 183 | } 184 | } 185 | 186 | ?> 187 | -------------------------------------------------------------------------------- /src/TopPHP/DBL.php: -------------------------------------------------------------------------------- 1 | features = 94 | [ 95 | "auto_stats" => [false], 96 | "safety" => false, 97 | "webhook" => [] 98 | ]; 99 | 100 | if($parameters["auto_stats"]) $this->features["auto_stats"][0] = true; 101 | if($parameters["safety"]) $this->features["safety"] = true; 102 | if($parameters["webhook"]) $this->features["webhook"] = true; 103 | if($parameters["token"]) $this->token = $parameters["token"]; 104 | else throw new MissingTokenException(); 105 | 106 | $this->http = (!$parameters["webhook"]["url"]) ? Request::SERVER_ADDR : $parameters["webhook"]["url"]; 107 | $this->port = (!$parameters["webhook"]["port"]) ? Request::SERVER_PORT : $parameters["webhook"]["port"]; 108 | $this->api = new Request($this->token, $this->http); 109 | 110 | /** Proxy an HTTP request to see if it works. */ 111 | $_response = $this->api->req("GET", "/users/140862798832861184")["status"]; 112 | if($_response === "200") $this->connected = true; 113 | 114 | /** Finally do our feature checks from the parameters list. */ 115 | if($parameters["auto_stats"]) 116 | { 117 | $this->check_auto_stats( 118 | $parameters["auto_stats"]["url"], 119 | $parameters["auto_stats"]["id"] 120 | ); 121 | } 122 | 123 | $this->check_safety(); 124 | } 125 | 126 | /** 127 | * Checks if stats should be posted to the website automatically. 128 | * This can only be done for a website URL. 129 | * 130 | * @param string $path The HTTP path you're using. 131 | * @param int $id The bot ID. 132 | * @param array $values A list of values to be automatically posted. 133 | * @return void 134 | */ 135 | protected function check_auto_stats(string $path, int $id, array $values) 136 | { 137 | try 138 | { 139 | if($values["shards"]) $_json["shards"] = $values["shards"]; 140 | if($values["shard_id"]) $_json["shard_id"] = $values["shard_id"]; 141 | if($values["shard_count"]) $_json["shard_count"] = $values["shard_count"]; 142 | if($values["server_count"]) $_json["server_count"] = $values["server_count"]; 143 | else throw new MissingStatsException(); 144 | 145 | $_id = ($id) ? $id : throw new MissingStatsException(); 146 | $_url = ($path) ? $path : throw new MissingStatsException(); 147 | $_type = Http::BOT; 148 | $_request = $this->api->req("POST", "/{$_type}/{$_id}/stats", $_json)["json"]; 149 | } 150 | 151 | catch(Exception $error) { echo $error; } 152 | 153 | finally 154 | { 155 | header("Content-Type: application/json"); 156 | echo ""; 157 | } 158 | } 159 | 160 | /** 161 | * Checks if the person wants a safety lock on the class. 162 | * Basically runs a very quick magic constant to automatically 163 | * delete the class instance as soon as detected. (Faster way) 164 | * 165 | * @return void 166 | */ 167 | protected function check_safety() 168 | { 169 | /** One last time to check. */ 170 | if($this->features["safety"]) die(); 171 | } 172 | 173 | /** 174 | * Shows the information from the specified type through a query search. 175 | * 176 | * @param string $type The search type. 177 | * @param array $json The JSON query fields, with key:val as assoc. 178 | * @return array 179 | */ 180 | public function show_info(string $type, array $json = []): array 181 | { 182 | switch($type) 183 | { 184 | case Http::USER: 185 | $_path = "users"; 186 | break; 187 | 188 | case Http::BOT: 189 | $_path = "bots"; 190 | break; 191 | 192 | default: 193 | die("Invalid search parameter: {$type}"); 194 | break; 195 | } 196 | 197 | return $this->api->req("GET", "/{$type}", $json)["json"]; 198 | } 199 | 200 | /** 201 | * Displays the general information about something 202 | * given through the search type. 203 | * 204 | * @param string $type The search type. 205 | * @param int $id The bot/user ID. 206 | * @return array 207 | */ 208 | public function find_info(string $type, int $id): array 209 | { 210 | switch($type) 211 | { 212 | case Http::USER: 213 | $_path = "users"; 214 | break; 215 | 216 | case Http::BOT: 217 | $_path = "bots"; 218 | break; 219 | 220 | default: 221 | die("Invalid search parameter: {$type}"); 222 | break; 223 | } 224 | 225 | return $this->api->req("GET", "/{$type}/{$id}")["json"]; 226 | } 227 | 228 | /** 229 | * Returns the total votes of the bot. 230 | * 231 | * @param int $id The bot ID. 232 | * @return array 233 | */ 234 | public function get_votes(int $id) 235 | { 236 | return $this->api->req("GET", "/bots/{$id}/votes")["json"]; 237 | } 238 | 239 | /** 240 | * Returns a boolean check for if a user voted for your bot. 241 | * 242 | * @param int $id The bot user ID. 243 | * @param int $user The user Snowflake ID. 244 | * @return array 245 | */ 246 | public function get_user_vote(int $id, int $user): array 247 | { 248 | return $this->api->req("GET", "/bots/{$id}/check", ["userId" => $user])["json"]["voted"]; 249 | } 250 | 251 | /** 252 | * Returns the statistics of the bot. 253 | * 254 | * @param int $id The bot ID. 255 | * @return array 256 | */ 257 | public function get_stats(int $id): array 258 | { 259 | return $this->api->req("GET", "/bots/{$id}/stats")["json"]; 260 | } 261 | 262 | /** 263 | * Posts statistics to the bot's Top.gg page. 264 | * 265 | * @param int $id The bot ID. 266 | * @param array $json The JSON query fields. 267 | * @return array 268 | */ 269 | public function post_stats(int $id, array $json): array 270 | { 271 | return $this->api->req("POST", "/bots/{$id}/stats", $json)["json"]; 272 | } 273 | 274 | /** 275 | * Returns the current HTTP address. 276 | * 277 | * @return string 278 | */ 279 | public function getHttp(): string 280 | { 281 | return $this->http; 282 | } 283 | 284 | /** 285 | * Returns the current HTTP port serial identification. 286 | * 287 | * @return int 288 | */ 289 | public function getPort(): int 290 | { 291 | return $this->port; 292 | } 293 | 294 | /** 295 | * Returns the current HTTP request. 296 | * 297 | * @return array 298 | */ 299 | public function getContents(): array 300 | { 301 | return $this->api->getContents(); 302 | } 303 | 304 | /** 305 | * Returns the last parsed HTTP request. 306 | * 307 | * @return array 308 | */ 309 | public function getCache(): array 310 | { 311 | return $this->api->getCache(); 312 | } 313 | 314 | /** 315 | * Returns the current HTTP response code. 316 | * (Not to be confused with the cached version in getCache()) 317 | * 318 | * @return string 319 | */ 320 | public function getResponse(): string 321 | { 322 | return $this->api->getResponse(); 323 | } 324 | } 325 | 326 | ?> 327 | --------------------------------------------------------------------------------