├── .gitignore ├── CODEOWNERS ├── LICENSE ├── README.md ├── babel.config.js ├── docs ├── API │ ├── @reference.mdx │ ├── bot.mdx │ └── user.mdx ├── Libraries │ ├── dotnet.mdx │ ├── go.mdx │ ├── java.mdx │ ├── javascript.mdx │ ├── php.mdx │ ├── python.mdx │ ├── ruby.mdx │ └── rust.mdx ├── Resources │ ├── ratelimits.mdx │ └── webhooks.mdx └── index.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── sidebars.js ├── src ├── components │ ├── HTTPHeader.jsx │ ├── Logo.jsx │ └── Message.jsx ├── css │ └── custom.css └── pages │ └── index.js └── static ├── .nojekyll ├── img ├── favicon.ico └── logo.svg └── logo.svg /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | .cache/ -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | content/libraries/python.mdx @null8626 2 | content/libraries/javascript.mdx @jpbberry @xetera 3 | content/libraries/dotnet.mdx @velddev @faith-ie 4 | content/libraries/go.mdx @rumblefrog 5 | content/libraries/php.mdx @goverfl0w 6 | content/libraries/java.mdx @nikammerlaan 7 | content/libraries/rust.mdx @null8626 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/API/@reference.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | # files that should be pinned to the top like reference 3 | # are prefixed with a @ symbol 4 | title: 🌟 Getting Started 5 | description: Basics of the API 6 | --- 7 | 8 | Our API is HTTPS/REST for general operations such as sending `POST` requests and receiving `GET` requests. 9 | 10 | #### Base Url 11 | 12 | [https://top.gg/api](https://top.gg/api) 13 | 14 | ## Authentication 15 | 16 | To access our API you need to authorize yourself, this can be done by using your discord bot list token. Your token can be obtained from your bot page settings under **Webhooks** (https://top.gg/bot/:yourbotid/webhooks replacing `:yourbotid` with the ID of your bot). 17 | 18 | Authentication is performed with the `Authorization` HTTP header as such 19 | 20 | ```json:title=HTTP%20Headers 21 | { 22 | "Authorization": "your-topgg-token-here" 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/API/bot.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bots 3 | description: API resource for a bots or apps on a platform like Discord 4 | --- 5 | 6 | import HTTPHeader from "../../src/components/HTTPHeader"; 7 | 8 | > Bot endpoints are subject to [stricter rate limits](/docs/Resources/ratelimits#resource-specific-ratelimits) than others. 9 | 10 | ## Search Bots 11 | 12 | 13 | 14 | 15 | Gets a list of bots that match a specific query. 16 | 17 | ### Query String Parameters 18 | 19 | | Field | Type | Description | Default | 20 | | ------ | -------- | -------------------------------------------------------------- | ---------- | 21 | | limit | `number` | The amount of bots to return. Max. 500 | 50 | 22 | | offset | `number` | Amount of bots to skip | 0 | 23 | | sort | `string` | The field to sort by. Prefix with - to reverse the order | | 24 | | fields | `string` | A comma separated list of fields to show | All fields | 25 | 26 | ### Response Fields 27 | 28 | | Field | Type | Description | 29 | | ------- | ------------------------- | --------------------------------------------- | 30 | | results | [`Bot[]`](#bot-structure) | The matching bots | 31 | | limit | `number` | The limit used | 32 | | offset | `number` | The offset used | 33 | | count | `number` | The length of the results array | 34 | | total | `number` | The total number of bots matching your search | 35 | 36 | ```json:title=/bots?search%3DLuca 37 | { 38 | "results": [ 39 | { 40 | "defAvatar": "6debd47ed13483642cf09e832ed0bc1b", 41 | "invite": "", 42 | "website": "https://discordbots.org", 43 | "support": "KYZsaFb", 44 | "github": "https://github.com/DiscordBotList/Luca", 45 | "longdesc": "Luca only works in the **Discord Bot List** server. \r\nPrepend commands with the prefix `-` or `@Luca#1375`. \r\n**Please refrain from using these commands in non testing channels.**\r\n- `botinfo @bot` Shows bot info, title redirects to site listing.\r\n- `bots @user`* Shows all bots of that user, includes bots in the queue.\r\n- `owner / -owners @bot`* Shows all owners of that bot.\r\n- `prefix @bot`* Shows the prefix of that bot.\r\n* Mobile friendly version exists. Just add `noembed` to the end of the command.\r\n", 46 | "shortdesc": "Luca is a bot for managing and informing members of the server", 47 | "prefix": "- or @Luca#1375", 48 | "clientid": "264811613708746752", 49 | "avatar": "7edcc4c6fbb0b23762455ca139f0e1c9", 50 | "id": "264811613708746752", 51 | "discriminator": "1375", 52 | "username": "Luca", 53 | "date": "2017-04-26T18:08:17.125Z", 54 | "server_count": 2, 55 | "guilds": ["417723229721853963", "264445053596991498"], 56 | "shards": [], 57 | "monthlyPoints": 19, 58 | "points": 397, 59 | "certifiedBot": false, 60 | "owners": ["129908908096487424"], 61 | "tags": ["Moderation", "Role Management", "Logging"], 62 | "donatebotguildid": "" 63 | } 64 | ], 65 | "limit": 1, 66 | "offset": 0, 67 | "count": 1, 68 | "total": 7 69 | } 70 | ``` 71 | 72 | ## Find One Bot 73 | 74 | 75 | 76 | Finds a single bot 77 | 78 | ### Example Response 79 | 80 | [`Bot`](/docs/API/bot/#example-structure) **or** 404 81 | 82 | ## Last 1000 Votes 83 | 84 | 85 | 86 | Gets the last 1000 voters for your bot. 87 | 88 | > If your bot receives more than 1000 votes monthly you cannot use this endpoints and must use `webhooks` and implement your own caching instead. 89 | 90 | > This endpoint only returns unique votes, it does not include double votes (weekend votes). 91 | 92 | This example uses Luca but users are restricted to only receiving their own bots' votes. Replace the id with your own bot. 93 | 94 | ### Example Response 95 | 96 | ```json:title=/bots/1234/votes 97 | [ 98 | { 99 | "username": "Xetera", 100 | "id": "140862798832861184", 101 | "avatar": "a_1241439d430def25c100dd28add2d42f" 102 | } 103 | ] 104 | ``` 105 | 106 | ## Bot stats 107 | 108 | 109 | 110 | Specific stats about a bot. 111 | 112 | ### Response 113 | 114 | | Field | Type | Description | 115 | | ------------- | ---------- | ------------------------------------------------------------------------------ | 116 | | server_count? | `number` | The amount of servers the bot is in | 117 | | shards | `number[]` | The amount of servers the bot is in per shard. Always present but can be empty | 118 | | shard_count? | `number` | The amount of shards a bot has | 119 | 120 | ## Individual User Vote 121 | 122 | 123 | 124 | Checking whether or not a user has voted for your bot. Safe to use even if you have over 1k monthly votes. 125 | 126 | ### Params 127 | 128 | | Field | Type | Description | 129 | | ------ | ----------- | ----------------- | 130 | | userId | `snowflake` | User's Discord ID | 131 | 132 | ### Example Response 133 | 134 | ```json:title=/bots/9876/check?userId%3D1234 135 | { 136 | "voted": 1 137 | } 138 | ``` 139 | 140 | ## Post Stats 141 | 142 | 143 | 144 | ### Post Body 145 | 146 | | Field | Type | Description | Required | 147 | | ------------ | ---------------------- | ------------------------------------------------------------------------------------------------- | -------- | 148 | | server_count | `number` \| `number[]` | Amount of servers the bot is in. If an Array, it acts like shards | ✔️ | 149 | | shards | `number[]` | Amount of servers the bot is in per shard. | ❌ | 150 | | shard_id | `number` | The zero-indexed id of the shard posting. Makes server_count set the shard specific server count. | ❌ | 151 | | shard_count | `number` | The amount of shards the bot has. | ❌ | 152 | 153 | ## Bot Structure 154 | 155 | | Field | Type | Description | 156 | | ---------------- | ------------- | ----------------------------------------------------------------------------- | 157 | | id | `string` | The id of the bot | 158 | | username | `string` | The username of the bot | 159 | | discriminator | `string` | The discriminator of the bot | 160 | | avatar? | `string` | The avatar hash of the bot's avatar | 161 | | defAvatar? | `string` | The cdn hash of the bot's avatar if the bot has none | 162 | | lib | `string` | The library of the bot | 163 | | prefix | `string` | The prefix of the bot | 164 | | shortdesc | `string` | The short description of the bot | 165 | | longdesc? | `string` | The long description of the bot. Can contain HTML and/or Markdown | 166 | | tags | `string[]` | The tags of the bot | 167 | | website? | `string` | The website url of the bot | 168 | | support? | `string` | The support server invite code of the bot | 169 | | github? | `string` | The link to the github repo of the bot | 170 | | owners | `snowflake[]` | of Snowflakes The owners of the bot. First one in the array is the main owner | 171 | | guilds | `snowflake[]` | of Snowflakes The guilds featured on the bot page | 172 | | invite? | `string` | The custom bot invite url of the bot | 173 | | date | `datestring` | The date when the bot was approved | 174 | | server_count? | `number` | The amount of servers the bot has according to posted stats. | 175 | | shard_count? | `number` | The amount of shards the bot has according to posted stats. | 176 | | certifiedBot | `boolean` | The certified status of the bot | 177 | | vanity? | `string` | The vanity url of the bot | 178 | | points | `number` | The amount of upvotes the bot has | 179 | | monthlyPoints | `number` | The amount of upvotes the bot has this month | 180 | | donatebotguildid | `string` | The guild id for the donatebot setup | 181 | 182 | ### Example Structure 183 | 184 | ```json 185 | { 186 | "defAvatar": "6debd47ed13483642cf09e832ed0bc1b", 187 | "invite": "", 188 | "website": "https://discordbots.org", 189 | "support": "KYZsaFb", 190 | "github": "https://github.com/DiscordBotList/Luca", 191 | "longdesc": "Luca only works in the **Discord Bot List** server. \r\nPrepend commands with the prefix `-` or `@Luca#1375`. \r\n**Please refrain from using these commands in non testing channels.**\r\n- `botinfo @bot` Shows bot info, title redirects to site listing.\r\n- `bots @user`* Shows all bots of that user, includes bots in the queue.\r\n- `owner / -owners @bot`* Shows all owners of that bot.\r\n- `prefix @bot`* Shows the prefix of that bot.\r\n* Mobile friendly version exists. Just add `noembed` to the end of the command.\r\n", 192 | "shortdesc": "Luca is a bot for managing and informing members of the server", 193 | "prefix": "- or @Luca#1375", 194 | "clientid": "264811613708746752", 195 | "avatar": "7edcc4c6fbb0b23762455ca139f0e1c9", 196 | "id": "264811613708746752", 197 | "discriminator": "1375", 198 | "username": "Luca", 199 | "date": "2017-04-26T18:08:17.125Z", 200 | "server_count": 2, 201 | "shard_count": 1, 202 | "guilds": ["417723229721853963", "264445053596991498"], 203 | "shards": [], 204 | "monthlyPoints": 19, 205 | "points": 397, 206 | "certifiedBot": false, 207 | "owners": ["129908908096487424"], 208 | "tags": ["Moderation", "Role Management", "Logging"], 209 | "donatebotguildid": "" 210 | } 211 | ``` 212 | -------------------------------------------------------------------------------- /docs/API/user.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Users 3 | description: API resource for Top.gg users 4 | --- 5 | 6 | import HTTPHeader from "../../src/components/HTTPHeader"; 7 | 8 | A user represents a User account in top.gg. It is not associated with any other platform like Discord. 9 | 10 | ## Find One User 11 | 12 | 13 | 14 | Retrieves information about a particular user by their Discord user id. 15 | 16 | ```bash 17 | curl -X GET https://top.gg/api/users/140862798832861184 \ 18 | -H 'Content-Type: application/json' \ 19 | -H 'Authorization: your-topgg-token' 20 | ``` 21 | 22 | ## Structure 23 | 24 | | Field | Type | Description | 25 | | ----------------- | ----------- | ----------------------------------------------------------------- | 26 | | id | `snowflake` | The id of the user | 27 | | username | `string` | The username of the user | 28 | | discriminator | `string` | The discriminator of the user | 29 | | avatar? | `string` | The avatar hash of the user's avatar | 30 | | defAvatar | `string` | The cdn hash of the user's avatar if the user has none | 31 | | bio? | `string` | The bio of the user | 32 | | banner? | `string` | The banner image url of the user | 33 | | social | `object` | The social usernames of the user | 34 | | social.youtube? | `string` | The youtube channel id of the user | 35 | | social.reddit? | `string` | The reddit username of the user | 36 | | social.twitter? | `string` | The twitter username of the user | 37 | | social.instagram? | `string` | The instagram username of the user | 38 | | social.github? | `string` | The github username of the user | 39 | | color? | `string` | The custom hex color of the user (not guaranteed to be valid hex) | 40 | | supporter | `boolean` | The supporter status of the user | 41 | | certifiedDev | `boolean` | The certified status of the user | 42 | | mod | `boolean` | The mod status of the user | 43 | | webMod | `boolean` | The website moderator status of the user | 44 | | admin | `boolean` | The admin status of the user | 45 | 46 | ```json 47 | { 48 | "discriminator": "0001", 49 | "avatar": "a_1241439d430def25c100dd28add2d42f", 50 | "id": "140862798832861184", 51 | "username": "Xetera", 52 | "defAvatar": "322c936a8c8be1b803cd94861bdfa868", 53 | "admin": true, 54 | "webMod": true, 55 | "mod": true, 56 | "certifiedDev": false, 57 | "supporter": false, 58 | "social": {} 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /docs/Libraries/dotnet.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Dotnet 3 | description: Top.gg Dotnet library 4 | --- 5 | 6 | # Dotnet Library 7 | 8 | The community-maintained .NET Library for Top.gg. If you experience any issues please submit an issue on Github. 9 | 10 | - [GitHub Link](https://github.com/top-gg/DBL-dotnet-Library) 11 | 12 | ## Installation 13 | 14 | ### Nuget 15 | 16 | If you're using Nuget you can use and/or find it with the ID DiscordBotsList.Api or use. 17 | 18 | ``` 19 | Install-Package DiscordBotsList.Api 20 | ``` 21 | 22 | ## Usage 23 | 24 | ### Unauthorized API Usage 25 | 26 | #### Setting Up 27 | 28 | ```cs 29 | DiscordBotListApi DblApi = new DiscordBotListApi(); 30 | ``` 31 | 32 | #### Getting Bots 33 | 34 | ```cs 35 | // discord id 36 | IBot bot = DblApi.GetBotAsync(160105994217586689); 37 | ``` 38 | 39 | #### Getting Users 40 | 41 | ```cs 42 | // discord id 43 | IUser bot = DblApi.GetUserAsync(121919449996460033); 44 | ``` 45 | 46 | ### Authorized API Usage 47 | 48 | #### Setting Up 49 | 50 | ```cs 51 | AuthDiscordBotListApi DblApi = new AuthDiscordBotListApi(BOT_DISCORD_ID, YOUR_TOKEN); 52 | ``` 53 | 54 | #### Updating Stats 55 | 56 | ```cs 57 | ISelfBot me = await DblApi.GetMeAsync(); 58 | await me.UpdateStatsAsync( 59 | // indexShard 60 | 24, 61 | // shardCount 62 | 50, 63 | // shards 64 | new[] { 12, 421, 62, 241, 524, 534 } 65 | ); 66 | 67 | // Update stats guildCount 68 | await me.UpdateStatsAsync(2133); 69 | ``` 70 | 71 | ### Widgets 72 | 73 | ```cs 74 | string widgetUrl = new SmallWidgetOptions() 75 | .SetType(WidgetType.OWNER) 76 | .SetLeftColor(255, 255, 255) 77 | .Build(160105994217586689); 78 | ``` 79 | 80 | Generates the following: 81 | ![](https://camo.githubusercontent.com/32783ef6b26ffe1a732b96a63d5dfc63608ef8d9/68747470733a2f2f646973636f7264626f74732e6f72672f6170692f7769646765742f7374617475732f3136303130353939343231373538363638392e7376673f6c656674636f6c6f723d464646464646) 82 | -------------------------------------------------------------------------------- /docs/Libraries/go.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Go 3 | description: Top.gg Go library 4 | --- 5 | 6 | # Go Library 7 | 8 | The community-maintained Go Library for Top.gg. If you experience any issues/bugs please submit an issue on Github. 9 | 10 | - [GitHub Link](https://github.com/top-gg/go-sdk) 11 | 12 | ## Usage 13 | 14 | Please refer to the github docs 15 | -------------------------------------------------------------------------------- /docs/Libraries/java.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Java 3 | description: Top.gg Java library 4 | --- 5 | 6 | # Java Library 7 | 8 | The community-maintained Java library for Top.gg. If you experience any issues/bugs please submit an issue on Github. 9 | 10 | - [GitHub](https://github.com/top-gg/Java-SDK) 11 | 12 | ## Installation 13 | 14 | Replace `VERSION` with the latest version or commit hash. The latest version can be found under [releases](https://github.com/top-gg/java-sdk/releases). 15 | 16 | #### Maven 17 | 18 | ```xml 19 | 20 | 21 | jitpack.io 22 | https://jitpack.io 23 | 24 | 25 | ``` 26 | 27 | ```xml 28 | 29 | 30 | org.discordbots 31 | DBL-Java-Library 32 | VERSION 33 | 34 | 35 | ``` 36 | 37 | #### Gradle 38 | 39 | ```gradle 40 | repositories { 41 | maven { url 'https://jitpack.io' } 42 | } 43 | ``` 44 | 45 | ```gradle 46 | dependencies { 47 | compile 'org.discordbots:DBL-Java-Library:VERSION' 48 | } 49 | ``` 50 | 51 | ## Usage 52 | 53 | First, build a DiscordBotListAPI object. 54 | 55 | ```java 56 | DiscordBotListAPI api = new DiscordBotListAPI.Builder() 57 | .token("token") 58 | .botId("botId") 59 | .build(); 60 | ``` 61 | 62 | ## Posting bot stats 63 | 64 | Top.gg provides three ways to post your bots stats. 65 | **#1** Post the server count for the whole bot. 66 | 67 | ```java 68 | int serverCount = ...; // the total amount of servers across all shards 69 | 70 | api.setStats(serverCount); 71 | ``` 72 | 73 | **#2** Post the server count for an individual shard 74 | 75 | ```java 76 | int shardId = ...; // the id of this shard 77 | int shardCount = ...; // the amount of shards 78 | int serverCount = ...; // the server count of this shard 79 | 80 | api.setStats(shardId, shardCount, serverCount); 81 | ``` 82 | 83 | **#3** Post the server counts for every shard within a single request. 84 | 85 | ```java 86 | List shardServerCounts = ...; // a list of all the shards' server counts 87 | 88 | api.setStats(shardServerCounts); 89 | ``` 90 | 91 | ## Checking votes 92 | 93 | You can use this to tell if a user has voted for your bot before. 94 | 95 | ```java 96 | String userId = ...; // ID of the user you're checking 97 | api.hasVoted(userId).whenComplete((hasVoted, e) -> { 98 | if(hasVoted) 99 | System.out.println("This person has voted!"); 100 | else 101 | System.out.println("This person has not voted!"); 102 | }); 103 | ``` 104 | 105 | ## Get vote multiplier 106 | 107 | Use this to check if there is a vote multiplier applied at the moment. 108 | 109 | ```java 110 | api.getVotingMultiplier().whenComplete((multiplier, e) -> { 111 | if(multiplier.isWeekend()) 112 | System.out.println("It's the weekend, so votes are worth 2x!"); 113 | else 114 | System.out.println("It's not the weekend :pensive:"); 115 | }); 116 | ``` 117 | -------------------------------------------------------------------------------- /docs/Libraries/javascript.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: JavaScript 3 | description: Official Top.gg JavaScript library 4 | --- 5 | 6 | ## Links 7 | [Documentation](https://topgg.js.org) 8 | 9 | [NPM Package](https://npmjs.com/package/@top-gg/sdk) 10 | 11 | [GitHub](https://github.com/top-gg/node-sdk) 12 | 13 | ## Installation 14 | 15 | `npm install @top-gg/sdk` or `yarn add @top-gg/sdk` 16 | 17 | If you're using deno, check out the [unofficial deno sdk](https://github.com/link-discord/topgg-deno) 18 | 19 | ## Posting bot stats 20 | 21 | Posting your bot's statistics is a quick and easy way to show how many people use your bot. There's a simple library that uses our SDK to post statistics here: [topgg-autoposter](https://npmjs.com/package/topgg-autoposter) 22 | 23 | `npm i topgg-autoposter` 24 | 25 | ```js:title=/index.js 26 | const client = new Discord.Client() // Your discord.js or eris client (or djs ShardingManager) 27 | const { AutoPoster } = require('topgg-autoposter') 28 | 29 | const ap = AutoPoster('Your Top.gg Token', client) 30 | 31 | ap.on('posted', () => { 32 | console.log('Posted stats to Top.gg!') 33 | }) 34 | ``` 35 | 36 | ## Webhooks 37 | 38 | The API can also be configured to receive events for when users vote for your bot through webhooks via express. You must first configure webhooks on your bot through the dashboard before using this. 39 | 40 | ```js:title=/index.js 41 | const Topgg = require("@top-gg/sdk") 42 | const express = require("express") 43 | 44 | const app = express() 45 | 46 | const webhook = new Topgg.Webhook("your webhook auth") 47 | 48 | app.post("/dblwebhook", webhook.listener(vote => { 49 | // vote will be your vote object, e.g 50 | console.log(vote.user) // 395526710101278721 < user who voted\ 51 | 52 | // You can also throw an error to the listener callback in order to resend the webhook after a few seconds 53 | })) 54 | 55 | app.listen(80) 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/Libraries/php.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PHP 3 | description: Top.gg PHP library 4 | --- 5 | 6 | # PHP Library 7 | 8 | The community-maintained PHP Library for Top.gg. If you experience any issues, please submit an issue on GitHub. 9 | 10 | - [GitHub Link](https://github.com/top-gg/php-sdk) 11 | 12 | ## Installation 13 | 14 | ### Install via composer (recommended) 15 | 16 | ``` 17 | composer require top-gg/php-sdk 18 | ``` 19 | 20 | ## Examples 21 | 22 | ### Getting Started 23 | 24 | This library does certain things differently from other API wrappers because it follows PHP's PSR standards. 25 | Below is sample code on how to initialize and use the API wrapper. 26 | 27 | ```php 28 | # Automatically load up the source library code. 29 | include_once __DIR__ . "vendor/autoload.php"; 30 | 31 | use DBL\DBL; 32 | 33 | $api = new DBL([ 34 | "token" => "YOUR TOP.GG API TOKEN HERE." 35 | ]); 36 | ``` 37 | 38 | Below are the currently accepted list of parameters when initializing the API. 39 | 40 | | Option | Type | Description | Optional? | 41 | | ------------ | --------- | -------------------------------- | --------- | 42 | | `token` | `string` | The token key of the Top.gg API. | No | 43 | | `auto_stats` | `array[]` | Details for automatic stats. | Yes | 44 | | `safety` | `bool` | Webserver code protection. | Yes | 45 | 46 | The API wrapper also presents you with a boolean instance, `connected` which may be used 47 | to check if your API token key is still valid or not. 48 | 49 | ### Get statistics from Top.gg 50 | 51 | In order to get statistics about a bot or user from Top.gg, you are able to select between 52 | the two interchangably with the same method: `find_info()`. 53 | 54 | ```php 55 | public function find_info(string $type, int $id): array 56 | ``` 57 | 58 | | Argument | Type | Description | 59 | | -------- | -------- | ----------------------------------------- | 60 | | `$type` | `string` | Whether you're looking for a bot or user. | 61 | | `$id` | `int` | The bot/user ID. | 62 | 63 | ```php 64 | use DBL\API\Http; 65 | 66 | if($api->connected) 67 | { 68 | /** 69 | * You will always be presented two constants to choose. 70 | * 71 | * Http::BOT = "bots" 72 | * Http::USER = "users" 73 | */ 74 | $user = $api->find_info(Http::USER, 242351388137488384); 75 | $bot = $api->find_info(Http::BOT, 799697654279307314); 76 | 77 | print_r($user) . print_r($bot) . PHP_EOL; 78 | } 79 | ``` 80 | 81 | ### Search for specific bots 82 | 83 | Similar to the same premise as using `find_info()`, you are able to additionally plug in 84 | query information that will be automatically formatted as a query-string URL search when 85 | an HTTP request is made by the API wrapper for you. This is known as `show_info()`. 86 | 87 | ```php 88 | public function show_info(string $type, array $json = []): array 89 | ``` 90 | 91 | | Argument | Type | Description | 92 | | -------- | -------- | ----------------------------------------- | 93 | | `$type` | `string` | Whether you're looking for a bot or user. | 94 | | `$json` | `array` | Information to plug into the search. | 95 | 96 | ```php 97 | use DBL\API\Http; 98 | 99 | if($api->connected) 100 | { 101 | $small_list = $api->show_info( 102 | Http::BOT, 103 | [ 104 | "limit" => 20, 105 | "sort" => "-" 106 | ] 107 | ); 108 | 109 | print_r($small_list) . PHP_EOL; 110 | } 111 | ``` 112 | 113 | ### Checking a vote from a user 114 | 115 | It's very important to be able and see if a user has voted for your bot. 116 | Below is the given example of how to do this. 117 | 118 | ```php 119 | public function get_user_vote(int $id, int $user): array 120 | ``` 121 | 122 | | Argument | Type | Description | 123 | | -------- | ----- | ------------------------ | 124 | | `$id` | `int` | The bot ID. | 125 | | `$user` | `int` | The user's snowflake ID. | 126 | 127 | ```php 128 | if($api->connected) 129 | { 130 | $isVoted = $api->get_user_vote(799697654279307314, 242351388137488384); 131 | if($isVoted) echo "This user voted!"; 132 | } 133 | ``` 134 | -------------------------------------------------------------------------------- /docs/Libraries/python.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Python 3 | description: Top.gg Python library 4 | --- 5 | 6 | # Python Library 7 | 8 | The community-maintained Python Library for Top.gg, if you experience any issues please submit an issue on our github. 9 | 10 | - [Full documentation](https://topggpy.rtfd.io/) 11 | - [GitHub link](https://github.com/top-gg/python-sdk) 12 | 13 | ## Installation 14 | 15 | ```console 16 | $ pip install topggpy 17 | ``` 18 | 19 | ## Documentation 20 | 21 | Documentation can be found [here](https://topggpy.rtfd.io). 22 | 23 | ## Features 24 | 25 | - POST server count 26 | - GET bot info, server count, upvote info 27 | - GET user info 28 | - GET widgets (large and small) including custom ones. See [docs.top.gg](https://docs.top.gg) for more info. 29 | - GET weekend status 30 | - Built-in webhook to handle Top.gg votes 31 | - Automated server count posting 32 | - Searching for bots via the API 33 | 34 | ## Additional information 35 | 36 | - Before using the webhook provided by this library, make sure that you have specified port open. 37 | - Optimal values for port are between 1024 and 49151. 38 | - If you happen to need help implementing topggpy in your bot, feel free to ask in the `#development` or `#api` channels in our [Discord server](https://discord.gg/dbl) -------------------------------------------------------------------------------- /docs/Libraries/ruby.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ruby 3 | description: A community maintained Top.gg Ruby Library 4 | --- 5 | 6 | # Ruby Library 7 | 8 | This is a community maintained Ruby Library for top.gg, if you have any issues/bugs please submit an issue on our github. 9 | 10 | - [GitHub Link](https://github.com/top-gg/ruby-sdk) 11 | 12 | ## Documentation 13 | 14 | - [Api Reference](https://rubydoc.info/gems/topgg/) 15 | 16 | ## Installation 17 | 18 | ```bash 19 | 20 | gem install topgg 21 | 22 | ``` 23 | 24 | ## Autoposting Statistics 25 | 26 | ```ruby 27 | require 'topgg' 28 | require 'discordrb' 29 | 30 | bot = Discordrb::Bot.new token: "TOKEN" 31 | 32 | client = Topgg.new("AUTH_TOKEN", "BOTID") 33 | bot.ready do |event| 34 | client.auto_post_stats(bot) # The discordrb bot client. 35 | end 36 | bot.run 37 | ``` 38 | 39 | ## Example Usage 40 | 41 | Here's an example on how to use the library! 42 | 43 | ```ruby 44 | require 'topgg' 45 | bot = Discordrb::Bot.new token: "TOKEN" 46 | 47 | client = Topgg.new("AUTH_TOKEN", "BOTID") 48 | # check if the speicified user id voted or not. 49 | p client.voted?("1234") 50 | ``` 51 | 52 | You can check out the [API Reference](https://rubydoc.info/gems/topgg/) to know about the other methods! 53 | -------------------------------------------------------------------------------- /docs/Libraries/rust.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rust 3 | description: Top.gg Rust library 4 | --- 5 | 6 | # [topgg](https://crates.io/crates/topgg) [![crates.io][crates-io-image]][crates-io-url] [![crates.io downloads][crates-io-downloads-image]][crates-io-url] 7 | 8 | [crates-io-image]: https://img.shields.io/crates/v/topgg?style=flat-square 9 | [crates-io-downloads-image]: https://img.shields.io/crates/d/topgg?style=flat-square 10 | [crates-io-url]: https://crates.io/crates/topgg 11 | 12 | The official Rust SDK for the [Top.gg API](https://docs.top.gg). 13 | 14 | ## Getting Started 15 | 16 | Make sure to have a [Top.gg API](https://docs.top.gg) token handy. If not, then [view this tutorial on how to retrieve yours](https://github.com/top-gg/rust-sdk/assets/60427892/d2df5bd3-bc48-464c-b878-a04121727bff). After that, add the following line to the `dependencies` section of your `Cargo.toml`: 17 | 18 | ```toml 19 | topgg = "1.4" 20 | ``` 21 | 22 | For more information, please read [the documentation](https://docs.rs/topgg)! 23 | 24 | ## Features 25 | 26 | This library provides several feature flags that can be enabled/disabled in `Cargo.toml`. Such as: 27 | 28 | - **`api`**: Interacting with the [Top.gg API](https://docs.top.gg) and accessing the `top.gg/api/*` endpoints. (enabled by default) 29 | - **`autoposter`**: Automating the process of periodically posting bot statistics to the [Top.gg API](https://docs.top.gg). 30 | - **`webhook`**: Accessing the [serde deserializable](https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html) `topgg::Vote` struct. 31 | - **`actix-web`**: Wrapper for working with the [actix-web](https://actix.rs/) web framework. 32 | - **`axum`**: Wrapper for working with the [axum](https://crates.io/crates/axum) web framework. 33 | - **`rocket`**: Wrapper for working with the [rocket](https://rocket.rs/) web framework. 34 | - **`warp`**: Wrapper for working with the [warp](https://crates.io/crates/warp) web framework. 35 | - **`serenity`**: Extra helpers for working with [serenity](https://crates.io/crates/serenity) library (with bot caching disabled). 36 | - **`serenity-cached`**: Extra helpers for working with [serenity](https://crates.io/crates/serenity) library (with bot caching enabled). 37 | - **`twilight`**: Extra helpers for working with [twilight](https://twilight.rs) library (with bot caching disabled). 38 | - **`twilight-cached`**: Extra helpers for working with [twilight](https://twilight.rs) library (with bot caching enabled). 39 | 40 | ## Examples 41 | 42 | ### Fetching a user from its Discord ID 43 | 44 | ```rust 45 | use topgg::Client; 46 | 47 | #[tokio::main] 48 | async fn main() { 49 | let client = Client::new(env!("TOPGG_TOKEN").to_string()); 50 | let user = client.get_user(661200758510977084).await.unwrap(); 51 | 52 | assert_eq!(user.username, "null"); 53 | assert_eq!(user.id, 661200758510977084); 54 | 55 | println!("{:?}", user); 56 | } 57 | ``` 58 | 59 | ### Posting your bot's statistics 60 | 61 | ```rust 62 | use topgg::{Client, Stats}; 63 | 64 | #[tokio::main] 65 | async fn main() { 66 | let client = Client::new(env!("TOPGG_TOKEN").to_string()); 67 | 68 | let server_count = 12345; 69 | client 70 | .post_stats(Stats::from(server_count)) 71 | .await 72 | .unwrap(); 73 | } 74 | ``` 75 | 76 | ### Checking if a user has voted your bot 77 | 78 | ```rust 79 | use topgg::Client; 80 | 81 | #[tokio::main] 82 | async fn main() { 83 | let client = Client::new(env!("TOPGG_TOKEN").to_string()); 84 | 85 | if client.has_voted(661200758510977084).await.unwrap() { 86 | println!("checks out"); 87 | } 88 | } 89 | ``` 90 | 91 | ### Autoposting with [serenity](https://crates.io/crates/serenity) 92 | 93 | In your `Cargo.toml`: 94 | 95 | ```toml 96 | [dependencies] 97 | # using serenity with guild caching disabled 98 | topgg = { version = "1.4", features = ["autoposter", "serenity"] } 99 | 100 | # using serenity with guild caching enabled 101 | topgg = { version = "1.4", features = ["autoposter", "serenity-cached"] } 102 | ``` 103 | 104 | In your code: 105 | 106 | ```rust 107 | use core::time::Duration; 108 | use serenity::{client::{Client, Context, EventHandler}, model::{channel::Message, gateway::Ready}}; 109 | use topgg::Autoposter; 110 | 111 | struct Handler; 112 | 113 | #[serenity::async_trait] 114 | impl EventHandler for Handler { 115 | async fn message(&self, ctx: Context, msg: Message) { 116 | if msg.content == "!ping" { 117 | if let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await { 118 | println!("Error sending message: {why:?}"); 119 | } 120 | } 121 | } 122 | 123 | async fn ready(&self, _: Context, ready: Ready) { 124 | println!("{} is connected!", ready.user.name); 125 | } 126 | } 127 | 128 | #[tokio::main] 129 | async fn main() { 130 | let topgg_client = topgg::Client::new(env!("TOPGG_TOKEN").to_string()); 131 | let autoposter = Autoposter::serenity(&topgg_client, Duration::from_secs(1800)); 132 | 133 | let bot_token = env!("DISCORD_TOKEN").to_string(); 134 | let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::GUILDS | GatewayIntents::MESSAGE_CONTENT; 135 | 136 | let mut client = Client::builder(&bot_token, intents) 137 | .event_handler(Handler) 138 | .event_handler_arc(autoposter.handler()) 139 | .await 140 | .unwrap(); 141 | 142 | if let Err(why) = client.start().await { 143 | println!("Client error: {why:?}"); 144 | } 145 | } 146 | ``` 147 | 148 | ### Autoposting with [twilight](https://twilight.rs) 149 | 150 | In your `Cargo.toml`: 151 | 152 | ```toml 153 | [dependencies] 154 | # using twilight with guild caching disabled 155 | topgg = { version = "1.4", features = ["autoposter", "twilight"] } 156 | 157 | # using twilight with guild caching enabled 158 | topgg = { version = "1.4", features = ["autoposter", "twilight-cached"] } 159 | ``` 160 | 161 | In your code: 162 | 163 | ```rust 164 | use core::time::Duration; 165 | use topgg::Autoposter; 166 | use twilight_gateway::{Event, Intents, Shard, ShardId}; 167 | 168 | #[tokio::main] 169 | async fn main() { 170 | let client = topgg::Client::new(env!("TOPGG_TOKEN").to_string()); 171 | let autoposter = Autoposter::twilight(&client, Duration::from_secs(1800)); 172 | 173 | let mut shard = Shard::new( 174 | ShardId::ONE, 175 | env!("DISCORD_TOKEN").to_string(), 176 | Intents::GUILD_MEMBERS | Intents::GUILDS, 177 | ); 178 | 179 | loop { 180 | let event = match shard.next_event().await { 181 | Ok(event) => event, 182 | Err(source) => { 183 | if source.is_fatal() { 184 | break; 185 | } 186 | 187 | continue; 188 | } 189 | }; 190 | 191 | autoposter.handle(&event).await; 192 | 193 | match event { 194 | Event::Ready(_) => { 195 | println!("Bot is ready!"); 196 | }, 197 | 198 | _ => {} 199 | } 200 | } 201 | } 202 | ``` 203 | 204 | ### Writing an [actix-web](https://actix.rs) webhook for listening to votes 205 | 206 | In your `Cargo.toml`: 207 | 208 | ```toml 209 | [dependencies] 210 | topgg = { version = "1.4", default-features = false, features = ["actix-web"] } 211 | ``` 212 | 213 | In your code: 214 | 215 | ```rust 216 | use actix_web::{ 217 | error::{Error, ErrorUnauthorized}, 218 | get, post, App, HttpServer, 219 | }; 220 | use std::io; 221 | use topgg::IncomingVote; 222 | 223 | #[get("/")] 224 | async fn index() -> &'static str { 225 | "Hello, World!" 226 | } 227 | 228 | #[post("/webhook")] 229 | async fn webhook(vote: IncomingVote) -> Result<&'static str, Error> { 230 | match vote.authenticate(env!("TOPGG_WEBHOOK_PASSWORD")) { 231 | Some(vote) => { 232 | println!("{:?}", vote); 233 | 234 | Ok("ok") 235 | } 236 | _ => Err(ErrorUnauthorized("401")), 237 | } 238 | } 239 | 240 | #[actix_web::main] 241 | async fn main() -> io::Result<()> { 242 | HttpServer::new(|| App::new().service(index).service(webhook)) 243 | .bind("127.0.0.1:8080")? 244 | .run() 245 | .await 246 | } 247 | ``` 248 | 249 | ### Writing an [axum](https://crates.io/crates/axum) webhook for listening to votes 250 | 251 | In your `Cargo.toml`: 252 | 253 | ```toml 254 | [dependencies] 255 | topgg = { version = "1.4", default-features = false, features = ["axum"] } 256 | ``` 257 | 258 | In your code: 259 | 260 | ```rust 261 | use axum::{routing::get, Router, Server}; 262 | use std::{net::SocketAddr, sync::Arc}; 263 | use topgg::{Vote, VoteHandler}; 264 | 265 | struct MyVoteHandler {} 266 | 267 | #[axum::async_trait] 268 | impl VoteHandler for MyVoteHandler { 269 | async fn voted(&self, vote: Vote) { 270 | println!("{:?}", vote); 271 | } 272 | } 273 | 274 | async fn index() -> &'static str { 275 | "Hello, World!" 276 | } 277 | 278 | #[tokio::main] 279 | async fn main() { 280 | let state = Arc::new(MyVoteHandler {}); 281 | 282 | let app = Router::new().route("/", get(index)).nest( 283 | "/webhook", 284 | topgg::axum::webhook(env!("TOPGG_WEBHOOK_PASSWORD").to_string(), Arc::clone(&state)), 285 | ); 286 | 287 | let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); 288 | 289 | Server::bind(&addr) 290 | .serve(app.into_make_service()) 291 | .await 292 | .unwrap(); 293 | } 294 | ``` 295 | 296 | ### Writing a [rocket](https://rocket.rs) webhook for listening to votes 297 | 298 | In your `Cargo.toml`: 299 | 300 | ```toml 301 | [dependencies] 302 | topgg = { version = "1.4", default-features = false, features = ["rocket"] } 303 | ``` 304 | 305 | In your code: 306 | 307 | ```rust 308 | #![feature(decl_macro)] 309 | 310 | use rocket::{get, http::Status, post, routes}; 311 | use topgg::IncomingVote; 312 | 313 | #[get("/")] 314 | fn index() -> &'static str { 315 | "Hello, World!" 316 | } 317 | 318 | #[post("/webhook", data = "")] 319 | fn webhook(vote: IncomingVote) -> Status { 320 | match vote.authenticate(env!("TOPGG_WEBHOOK_PASSWORD")) { 321 | Some(vote) => { 322 | println!("{:?}", vote); 323 | 324 | Status::Ok 325 | }, 326 | _ => { 327 | println!("found an unauthorized attacker."); 328 | 329 | Status::Unauthorized 330 | } 331 | } 332 | } 333 | 334 | fn main() { 335 | rocket::ignite() 336 | .mount("/", routes![index, webhook]) 337 | .launch(); 338 | } 339 | ``` 340 | 341 | ### Writing a [warp](https://crates.io/crates/warp) webhook for listening to votes 342 | 343 | In your `Cargo.toml`: 344 | 345 | ```toml 346 | [dependencies] 347 | topgg = { version = "1.4", default-features = false, features = ["warp"] } 348 | ``` 349 | 350 | In your code: 351 | 352 | ```rust 353 | use std::{net::SocketAddr, sync::Arc}; 354 | use topgg::{Vote, VoteHandler}; 355 | use warp::Filter; 356 | 357 | struct MyVoteHandler {} 358 | 359 | #[async_trait::async_trait] 360 | impl VoteHandler for MyVoteHandler { 361 | async fn voted(&self, vote: Vote) { 362 | println!("{:?}", vote); 363 | } 364 | } 365 | 366 | #[tokio::main] 367 | async fn main() { 368 | let state = Arc::new(MyVoteHandler {}); 369 | 370 | // POST /webhook 371 | let webhook = topgg::warp::webhook( 372 | "webhook", 373 | env!("TOPGG_WEBHOOK_PASSWORD").to_string(), 374 | Arc::clone(&state), 375 | ); 376 | 377 | let routes = warp::get().map(|| "Hello, World!").or(webhook); 378 | 379 | let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); 380 | 381 | warp::serve(routes).run(addr).await 382 | } 383 | ``` -------------------------------------------------------------------------------- /docs/Resources/ratelimits.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ratelimits 3 | description: Global and route-specific rate limits 4 | --- 5 | 6 | The HTTP API implements a process for limiting and preventing spam requests. API users that regularly hit and ignore the limit will be blocked from our platform. These rate limits are in place to help prevent the abuse and overload of our services. 7 | 8 | ## Global Ratelimit 9 | 10 | Global rate limits are applied on all routes 11 | 12 | | Route | Request Type | Max Requests | Throttle | 13 | | ----- | ------------ | ------------ | ------------ | 14 | | `*` | \* | 100/second | 1 hour block | 15 | 16 | ## Resource-Specific Ratelimits 17 | 18 | Certain endpoints have tighter restrictions on their rate limits. Global rate limits still apply to requests sent to these. 19 | 20 | | Route | Request Type | Max Requests | Throttle | 21 | | --------- | ------------ | ------------ | ------------ | 22 | | `/bots/*` | \* | 60/minute | 1 hour block | 23 | 24 | ## Exceeding a Rate Limit 25 | 26 | If you exceed the set rate limit for the API you will receive a HTTP 429 and be blocked from posting to the API for one hour. 27 | 28 | ```json:title=HTTP%20429 29 | { 30 | "retry-after": 3600 31 | } 32 | ``` 33 | 34 | | Field | Type | Description | 35 | | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 36 | | retry-after | integer | The timeout in seconds before you are able to send requests again. Learn more about this header [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) | 37 | -------------------------------------------------------------------------------- /docs/Resources/webhooks.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Webhooks 3 | description: Webhook integration for receiving vote data 4 | --- 5 | 6 | Instead of requesting our API to see the users who have voted for your bot, you can now use webhooks! Webhooks will send a `POST` request to a URL of your choice when your bot has been voted for. 7 | 8 | ## Getting Started 9 | 10 | Start by setting up your webhook URL in the edit form of your bot on this site, it can be found at https://top.gg/bot/:your-bot-id/webhooks (Replace `:your-bot-id` with your bot's ID!). Once you've entered the URL you want the webhook to be sent to, you're all set! If you need help setting up webhooks inside of your bot don't be afraid to ask in our [discord server](https://discord.gg/dbl) in the `#topgg-api` channel. 11 | 12 | ## Security 13 | 14 | On the edit page you can see another input for `Authorization`. Here you can provide a shared secret that you can check for on the server side. 15 | 16 | To verify requests are coming from us, look for the value in the `Authorization` header and make sure it is the same as the value you provided in the form. 17 | 18 | If you're running a firewall, you can whitelist the following IPs, which will be used to deliver webhooks for the foreseeable future. 19 | 20 | | IP | 21 | | ----------------- | 22 | | `159.203.105.187` | 23 | 24 | ## Acknowledgement 25 | 26 | Webhooks sent by top.gg **must** be acknowledged with a 200 response in order to be considered successful. Unsuccessful webhooks are [retried](#retrial). 27 | 28 | Top.gg libraries that handle webhooks acknowledge webhooks automatically. 29 | 30 | ## Timeouts 31 | 32 | Responses to webhooks must be returned within 5 seconds, otherwise they are considered a timeout and will be queued for a retry (if available). 33 | 34 | ## Retrial 35 | 36 | Webhook requests that time out or return a `5XX` status response (like 500) will be retried up to 10 times. The retry delay is increased exponentially per retry by `2^N` seconds, from a minimum delay of 1 second for the first retry up to 17 minutes for the tenth. 37 | 38 | Errors resulting with status `4XX` (like 404) will not be retried as these are considered user errors. 39 | 40 | ## Data Format 41 | 42 | The format of the data your webhook URL will receive in a `POST` request. 43 | 44 | ### Schema 45 | 46 | #### Bot Webhooks 47 | 48 | | Field | Type | Description | 49 | | --------- | ----------- | --------------------------------------------------------------------------------------------------- | 50 | | bot | `snowflake` | Discord ID of the bot that received a vote. | 51 | | user | `snowflake` | Discord ID of the user who voted. | 52 | | type | `string` | The type of the vote (should always be `"upvote"` except when using the test button it's `"test"`). | 53 | | isWeekend | `boolean` | Whether the weekend multiplier is in effect, meaning users votes count as two. | 54 | | query? | `string` | Query string params found on the /bot/:ID/vote page. Example: ?a=1&b=2. | 55 | 56 | #### Server Webhooks 57 | 58 | | Field | Type | Description | 59 | | ------ | ----------- | --------------------------------------------------------------------------------------------------- | 60 | | guild | `snowflake` | Discord ID of the guild that received a vote. | 61 | | user | `snowflake` | Discord ID of the user who voted. | 62 | | type | `string` | The type of the vote (should always be `"upvote"` except when using the test button it's `"test"`). | 63 | | query? | `string` | Query string params found on the /servers/:ID/vote page. Example: ?a=1&b=2. | 64 | 65 | ## More Events 66 | 67 | Looking for webhooks events other than votes? They are only available starting from **v1** of the API. 68 | 69 |
You are currently viewing v0.
70 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | description: Welcome to Top.gg 4 | --- 5 | 6 | Hi developer 🥰, welcome to top.gg developer docs. You are currently viewing **v0** of our API documentation. We're going to be working on the next version of the top.gg API (v1) soon, stay tuned! 7 | 8 | ## Getting Started 9 | 10 | If you're looking for API usage, [click here](/docs/API/@reference/) or go to the `API` section on the sidebar. 11 | 12 | ## Getting Help 13 | 14 | If you need some help or think you have spotted a problem with our API you can talk to us in our [`#topgg-api`](https://discord.com/channels/264445053596991498/412006692125933568) channel in our [discord server](https://discord.gg/EYHTgJX). 15 | 16 | You can ask questions about our community-maintained API Libraries or general queries about the API in the server. 17 | -------------------------------------------------------------------------------- /docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // `@type` JSDoc annotations allow editor autocompletion and type checking 3 | // (when paired with `@ts-check`). 4 | // There are various equivalent ways to declare your Docusaurus config. 5 | // See: https://docusaurus.io/docs/api/docusaurus-config 6 | 7 | import { themes as prismThemes } from 'prism-react-renderer'; 8 | 9 | /** @type {import('@docusaurus/types').Config} */ 10 | const config = { 11 | title: 'Top.gg Documentation', 12 | tagline: 'Spice up your Discord experience with our diverse range of Discord Bots!', 13 | favicon: 'img/favicon.ico', 14 | 15 | // Set the production url of your site here 16 | url: 'https://docs.top.gg', 17 | // Set the // pathname under which your site is served 18 | // For GitHub pages deployment, it is often '//' 19 | baseUrl: '/', 20 | 21 | // GitHub pages deployment config. 22 | // If you aren't using GitHub pages, you don't need these. 23 | organizationName: 'top-gg', // Usually your GitHub org/user name. 24 | projectName: 'docs', // Usually your repo name. 25 | 26 | onBrokenLinks: 'throw', 27 | onBrokenMarkdownLinks: 'warn', 28 | 29 | // Even if you don't use internationalization, you can use this field to set 30 | // useful metadata like html lang. For example, if your site is Chinese, you 31 | // may want to replace "en" with "zh-Hans". 32 | i18n: { 33 | defaultLocale: 'en', 34 | locales: ['en'], 35 | }, 36 | 37 | presets: [ 38 | [ 39 | 'classic', 40 | /** @type {import('@docusaurus/preset-classic').Options} */ 41 | ({ 42 | docs: { 43 | sidebarPath: './sidebars.js', 44 | // Please change this to your repo. 45 | // Remove this to remove the "edit this page" links. 46 | editUrl: 47 | 'https://github.com/top-gg/docs/tree/main/docs/', 48 | }, 49 | theme: { 50 | customCss: './src/css/custom.css', 51 | }, 52 | }), 53 | ], 54 | ], 55 | 56 | stylesheets: [ 57 | 'https://raw.githubusercontent.com/top-gg/docs/master/src/css/custom.css', 58 | ], 59 | 60 | onBrokenAnchors: 'log', 61 | 62 | themeConfig: 63 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 64 | ({ 65 | colorMode: { 66 | defaultMode: "dark" 67 | }, 68 | // Replace with your project's social card 69 | image: 'logo.svg', 70 | navbar: { 71 | title: 'Top.gg', 72 | logo: { 73 | alt: 'Top.gg Logo', 74 | src: 'logo.svg', 75 | }, 76 | items: [ 77 | { 78 | type: 'docSidebar', 79 | sidebarId: 'tutorialSidebar', 80 | position: 'right', 81 | label: 'Docs', 82 | }, 83 | { 84 | href: 'https://github.com/top-gg-community', 85 | label: 'Community GitHub', 86 | position: 'right', 87 | }, 88 | ], 89 | }, 90 | 91 | prism: { 92 | theme: prismThemes.github, 93 | darkTheme: prismThemes.dracula, 94 | additionalLanguages: ['csharp', 'java', 'javascript', 'php', 'ruby'] 95 | }, 96 | }), 97 | }; 98 | 99 | export default config; 100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@docusaurus/core": "3.1.1", 18 | "@docusaurus/preset-classic": "3.1.1", 19 | "@mdx-js/react": "^3.0.0", 20 | "clsx": "^2.0.0", 21 | "prism-react-renderer": "^2.3.0", 22 | "react": "^18.0.0", 23 | "react-copy-to-clipboard": "^5.1.0", 24 | "react-dom": "^18.0.0", 25 | "styled-components": "^6.1.8" 26 | }, 27 | "devDependencies": { 28 | "@docusaurus/module-type-aliases": "3.1.1", 29 | "@docusaurus/types": "3.1.1" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.5%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 3 chrome version", 39 | "last 3 firefox version", 40 | "last 5 safari version" 41 | ] 42 | }, 43 | "engines": { 44 | "node": ">=18.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], 18 | }; 19 | 20 | export default sidebars; 21 | -------------------------------------------------------------------------------- /src/components/HTTPHeader.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import { CopyToClipboard } from "react-copy-to-clipboard"; 4 | 5 | const mappings = { 6 | POST: { 7 | color: "#78b993", 8 | background: "#0e1712", 9 | border: "#193123", 10 | }, 11 | GET: { 12 | color: "#7979d4", 13 | background: "#212133", 14 | border: "#47476b", 15 | }, 16 | }; 17 | 18 | const HeaderWrapper = styled.div` 19 | border: 1px solid ${(props) => mappings[props.method].border}; 20 | background: ${(props) => mappings[props.method].background}; 21 | border-radius: 4px; 22 | display: flex; 23 | align-items: center; 24 | flex-flow: row wrap; 25 | justify-content: space-between; 26 | height: 100%; 27 | margin-bottom: 24px; 28 | `; 29 | 30 | const MethodName = styled.h2` 31 | color: ${(props) => mappings[props.method].color}; 32 | font-weight: 700; 33 | font-size: 14px; 34 | margin: 0 10px 0 0; 35 | `; 36 | 37 | const EndpointUrl = styled.span``; 38 | 39 | const CopyButton = styled.button` 40 | color: ${(props) => mappings[props.method].color}; 41 | background: inherit; 42 | font-size: 14px; 43 | border: none; 44 | cursor: pointer; 45 | height: 45px; 46 | align-items: center; 47 | font-weight: 500; 48 | padding: 0 10px; 49 | &:hover { 50 | filter: brightness(0.6); 51 | } 52 | `; 53 | 54 | const Header = styled.span` 55 | padding: 10px 15px; 56 | display: flex; 57 | align-items: center; 58 | `; 59 | 60 | export default function HTTPHeader({ type, path }) { 61 | const [copied, setCopy] = React.useState(false); 62 | React.useEffect(() => { 63 | if (copied) { 64 | setTimeout(() => setCopy(false), 3000); 65 | } 66 | }, [copied]); 67 | const BASE_URL = "https://top.gg/api/"; 68 | const fullUrl = new URL(path, BASE_URL).href; 69 | const url = path; 70 | return ( 71 | 72 |
73 | {type} 74 | $&"), 77 | }} 78 | /> 79 |
80 | setCopy(true)}> 81 | {copied ? "Copied!" : "Copy URL"} 82 | 83 |
84 | ); 85 | } 86 | -------------------------------------------------------------------------------- /src/components/Logo.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ReactComponent as Topgg } from "../assets/logo.svg"; 3 | 4 | function Logo() { 5 | return ( 6 |
7 | 8 |

9 | Top.gg Documentation 10 |

11 |
12 | ); 13 | } 14 | 15 | export default Logo; 16 | -------------------------------------------------------------------------------- /src/components/Message.jsx: -------------------------------------------------------------------------------- 1 | export default function Message({ type, title, children }) { 2 | return
{children}
; 3 | } 4 | -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #ff3366; 10 | --ifm-color-primary-dark: #ff3366AA; 11 | --ifm-color-primary-darker: #ff336699; 12 | --ifm-color-primary-darkest: #ff336666; 13 | --ifm-color-primary-light: #ff3366; 14 | --ifm-color-primary-lighter: #ff3366; 15 | --ifm-color-primary-lightest: #ff3366; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | 19 | --background: #fff; 20 | --ui: 0,0,0; 21 | } 22 | 23 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 24 | [data-theme='dark'] { 25 | --ifm-color-primary: #ff3366; 26 | --ifm-color-primary-dark: #ff3366AA; 27 | --ifm-color-primary-darker: #ff336699; 28 | --ifm-color-primary-darkest: #ff336666; 29 | --ifm-color-primary-light: #ff3366; 30 | --ifm-color-primary-lighter: #ff3366; 31 | --ifm-color-primary-lightest: #ff3366; 32 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 33 | 34 | --background: #070510; 35 | --ui: 255,255,255; 36 | } 37 | 38 | html { 39 | background: var(--background); 40 | } 41 | 42 | body { 43 | max-width: 1440px; 44 | margin: 0 auto; 45 | } 46 | 47 | .navbar.navbar--fixed-top { 48 | background: linear-gradient(0deg, transparent 0%, var(--background) 100%); 49 | box-shadow: none; 50 | } 51 | 52 | .navbar__brand { 53 | width: 100%; 54 | } 55 | 56 | .navbar__logo { 57 | width: 52px; 58 | height: 52px; 59 | filter: invert(1); 60 | } 61 | [data-theme='dark'] .navbar__logo { 62 | filter: invert(0); 63 | } 64 | 65 | .docItemCol_node_modules-\@docusaurus-theme-classic-lib-theme-DocItem-Layout-styles-module { 66 | padding-inline: 48px; 67 | } 68 | 69 | /* hide the default homepage. */ 70 | .theme-doc-sidebar-item-link [href="/docs/"] { 71 | display: none; 72 | } 73 | 74 | .theme-doc-sidebar-container { 75 | border-right: 1px solid rgba(var(--ui), 0.1) !important; 76 | } 77 | 78 | .table-of-contents__left-border { 79 | border-left: 1px solid rgba(var(--ui), 0.1); 80 | } 81 | 82 | a { 83 | color: unset; 84 | } 85 | a:hover { 86 | color: unset; 87 | text-decoration: underline; 88 | } -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import useBaseUrl from '@docusaurus/useBaseUrl'; 3 | 4 | export default function Home() { 5 | const url = useBaseUrl('/docs/'); 6 | useEffect(() => { 7 | window.location.href = url 8 | }, []); 9 | return null; 10 | } -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/top-gg/docs/f6878900df9b0a357894730a37d3136d4954b2aa/static/.nojekyll -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/top-gg/docs/f6878900df9b0a357894730a37d3136d4954b2aa/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | --------------------------------------------------------------------------------