From 8cd5df513267226dae435763e0dbd4b32be5f369 Mon Sep 17 00:00:00 2001 From: null8626 Date: Mon, 16 Jun 2025 17:16:12 +0700 Subject: [PATCH 01/27] feat: adapt to v0 --- .gitignore | 3 +- Gemfile | 5 +- Gemfile.lock | 9 +++- README.md | 28 +++++----- lib/lib.rb | 90 ++++++++++++++----------------- lib/topgg/bot.rb | 106 ++++++++++++------------------------- lib/topgg/botSearch.rb | 44 +++++++++------ lib/topgg/stats.rb | 18 ++----- lib/topgg/user.rb | 50 ++--------------- lib/topgg/utils/request.rb | 70 +++++++++++++----------- lib/topgg/votes.rb | 20 +++++-- topgg.gemspec | 39 +++++++------- 12 files changed, 209 insertions(+), 273 deletions(-) diff --git a/.gitignore b/.gitignore index 06de90a..b81217d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.bundle \ No newline at end of file +.bundle +*.gem \ No newline at end of file diff --git a/Gemfile b/Gemfile index f97a909..9390882 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,9 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" # Specify your gem's dependencies in topgg.gemspec gemspec -gem 'rake', '~> 13.0' +gem "rake", "~> 13.0" +gem "ostruct", "~> 0.6" diff --git a/Gemfile.lock b/Gemfile.lock index f90d67a..521f12b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,14 +6,21 @@ PATH GEM remote: https://rubygems.org/ specs: + ostruct (0.6.1) + power_assert (2.0.5) rake (13.0.6) + test-unit (3.6.8) + power_assert PLATFORMS + x64-mingw-ucrt x86_64-linux DEPENDENCIES + ostruct (~> 0.6) rake (~> 13.0) + test-unit (~> 3.1, >= 3.1.8) topgg! BUNDLED WITH - 2.2.22 + 2.6.7 diff --git a/README.md b/README.md index 26f3cce..9ec3aad 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,55 @@ # [Top.gg](https://top.gg) Ruby -The Top.gg Ruby SDK is a lighweight package, that allows you +The Top.gg Ruby SDK is a lighweight package, that allows you to fetch data from the top.gg api and post data such as statistics to the website. It provides you with numerous methods to interact with the API. + ## Dependencies -* Ruby +- Ruby ## Installation -``` bash +```bash gem install topgg ``` + ## Note You require a Token to interact with the Api. -The token can be found at `https://top.gg/bot/[YOUR_BOT_ID]/webhooks` +The token can be found at `https://top.gg/bot/[YOUR_BOT_ID]/webhooks` ## Example Here's a straightforward example of how to request data with the wrapper. ```ruby -require 'topgg' +require "topgg" client = Topgg.new("AUTH_TOKEN", "BOTID") -client.get_bot("1234").defAvatar +client.get_bot("1234").avatar # returns -# "6debd47ed13483642cf09e832ed0bc1b" - +# "https://cdn.discordapp.com/avatars/661200758510977084/4354318859c319c7ca39753260fdd350.png?size=4096" ``` + ### Auto Posting -The library provides you with autoposting functionality, and autoposts at an interval of 30 minutes. +The library provides you with autoposting functionality, and autoposts at an interval of 15 minutes. Here's how you can use it ```ruby -require 'topgg' -require 'discordrb' +require "topgg" +require "discordrb" bot = Discordrb::Bot.new token: "TOKEN" client = Topgg.new("AUTH_TOKEN", "BOTID") - bot.ready do |event| - client.auto_post_stats(bot) # The discordrb bot client. +bot.ready do |event| + client.auto_post_stats(bot) # The discordrb bot client. end bot.run ``` diff --git a/lib/lib.rb b/lib/lib.rb index 4bf0263..966c34f 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true -require_relative 'topgg/utils/request' -require 'json' -require_relative 'topgg/bot' -require_relative 'topgg/botSearch' -require_relative 'topgg/user' -require_relative 'topgg/stats' -require_relative 'topgg/votes' +require_relative "topgg/utils/request" +require "json" +require_relative "topgg/bot" +require_relative "topgg/botSearch" +require_relative "topgg/user" +require_relative "topgg/stats" +require_relative "topgg/votes" + # Class Topgg # The class instantiates all the methods for api requests and posts. class Topgg @@ -23,67 +24,58 @@ def initialize(token, id) # @param id [String] The id of the bot you want to fetch statistics from. # @return [Dbl::Bot] The Bot Object def get_bot(id) - resp = @request.get("bots/#{id}") - - Dbl::Bot.new(resp) + Dbl::Bot.new(@request.get("bots/#{id}")) end # The method searches bots from top.gg using a keyword query. # @param [Object] params The parameters that can be used to query a search # To know what the parameters are check it out here # @return [Dbl::BotSearch] The BotSearch Object - def search_bot(params) - resp = @request.get('bots/search', params) - Dbl::BotSearch.new(resp) - end - - # Search for a user on top.gg with id - # @param id [String] The id of the user to search for. - # @return [Dbl::User] - def user(id) - resp = @request.get("users/#{id}") - - Dbl::User.new(resp) + def get_bots(params) + Dbl::BotSearch.new(@request.get("bots", params)) end # Get Bot statistics. - # @param id [String] Id of the bot you want to get statistics of # @return [Dbl::Stats] - def get_stats(id) - resp = @request.get("bots/#{id}/stats") - - Dbl::Stats.new(resp) + def get_stats() + Dbl::Stats.new(@request.get("bots/stats")) end # Mini-method to query if the bot(self) was voted by the user. # @param userid [String] The user id. # @return [Boolean] def voted?(userid) - resp = @request.get("bots/#{@id}/check", { userId: userid }) + resp = @request.get("bots/check", { userId: userid }) + resp["voted"] == 1 + end - ret = resp - ret['voted'] == 1 + # Checks if the weekend multiplier is active, where a single vote counts as two. + # @return [Boolean] + def is_weekend? + resp = @request.get("weekend") + resp["is_weekend"] end - # Get the Last 1000 votes of the bot(self) + # Get the last 1000 unique votes of the bot(self) + # @param page [Integer] The page to use. Defaults to 1. # @return [Dbl::Votes] - def votes - resp = @request.get("bots/#{@id}/votes") + def votes(page = 1) + page = 1 if page.to_i < 1 + resp = @request.get("bots/#{@id}/votes", { page: page }) Dbl::Votes.new(resp) end # Post Bot Statistics to the website - # @param server_count [Integer] The amount of servers the bot is in. - # @param shards [Integer] The amount of servers the bot is in per shard - # @param shard_count [Integer] The total number of shards. - def post_stats(server_count, shards: nil, shard_count: nil) - json_post = { - server_count: server_count, - shards: shards, - shard_count: shard_count - }.to_json - @request.post("bots/#{@id}/stats", json_post, { 'Content-Type' => 'application/json' }) + # @param server_count [Integer] The amount of servers the bot is in. Must not be less than 1. + def post_stats(server_count) + raise ArgumentError, "server_count cannot be less than 1" unless server_count > 0 + + json_post = { server_count: server_count }.to_json + @request.post( + "bots/stats", + json_post + ) end # Auto-posts stats on to the top.gg website @@ -92,10 +84,12 @@ def auto_post_stats(client) semaphore = Mutex.new Thread.new do semaphore.synchronize do - interval 1800 do + interval 900 do server_len = client.servers.length post_stats(server_len) - print("[TOPGG] : \033[31;1;4m Bot statistics has been successfully posted!\033[0m") + puts( + "[TOPGG] : \033[31;1;4m Bot statistics has been successfully posted!\033[0m" + ) end end end @@ -110,11 +104,7 @@ def self def interval(seconds) loop do yield - sleep seconds + sleep seconds end end end - - - - diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index f0bad3d..b866cb2 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -1,3 +1,5 @@ +require "Date" + module Dbl # The Bot class spreads the json parsed hash into different methods class Bot @@ -10,169 +12,127 @@ def initialize(obj) # @return [Hash] attr_reader :obj - alias :raw :obj + alias raw obj alias data obj - # Returns error message, if there's an error + # Returns error message if there's an error, otherwise nil # @return [String] def error - @obj['error'].to_str - end - - # Returns the default Avatar of the client - # @return [String] - def defAvatar - @obj['defAvatar'].to_str + @obj["error"] end # Returns the invite link of the bot # @return [String] def invite - @obj['invite'].to_str + @obj["invite"] end # Returns the bot website, if configured # @return [String] def website - @obj['website'].to_str + @obj["website"] end # Returns support server link # @return [String] def support - "https://discord.gg/#{@obj['support']}" + @obj["support"] end # Returns github repository link, if any # @return [String] def github - @obj['github'].to_str + @obj["github"] end # Returns the long Description of the bot # @return [String] def longdesc - @obj['longdesc'].to_str + @obj["longdesc"] end # Returns the short description of the bot # @return [String] def shortdesc - @obj['shortdesc'].to_str + @obj["shortdesc"] end # Returns the default prefix of the bot # @return [String] def prefix - @obj['prefix'].to_str - end - - # Returns the bot library - # @return [String] - def lib - @obj['lib'].to_str + @obj["prefix"] end # Returns the bot client id # @return [String] def clientid - @obj['clientid'].to_str + @obj["clientid"] end # Returns the avatar link of the bot # @return [String] def avatar - "https://cdn.discordapp.com/avatars/#{@obj['id']}/#{@obj['avatar']}.webp?size=1024" + @obj["avatar"] end # Returns the bot id # @return [String] def id - @obj['id'].to_str - end - - # Returns the bot descriminator - # @return [String] - def descriminator - @obj['descriminator'].to_str + @obj["id"] end # Returns the bot username # @return [String] def username - @obj['username'].to_str + @obj["username"] end # Returns the date on which the bot was submitted # @return [Date] def date - Date.parse(@obj['date']) + Date.parse(@obj["date"]) end # Returns the server count of the bot # @return [Integer] def server_count - @obj['server_count'].to_i + @obj["server_count"].to_i end - # Returns the amount of shards - # @return [String] - def shard_count - @obj['shard_count'].to_str - end - - # Returns configured guilds in which the bot is in - # @return [String] - def guilds - @obj['guilds'].to_str - end - - # Returns the amount of guilds per shard of the bot - # @return [String] - def shards - @obj['shards'].to_str - end - - # Returns the monthyPoints of the bot - # @return [String] + # Returns the monthly vote count of the bot + # @return [Integer] def monthlyPoints - @obj['monthlyPoints'].to_str + @obj["monthlyPoints"].to_i end # Returns the total points of the bot - # @return [String] + # @return [Integer] def points - @obj['points'].to_str + @obj["points"].to_i end - # Returns true/false depending on if the bot is certified or not - # @return [Boolean] - def certifiedBot - @obj['certifiedBot'].to_str + # Returns the Top.gg vanity URL code, can be nil + # @return [String] + def vanity + @obj["vanity"] end # Returns the owner ids # @return [Array] def owners - @obj['owners'].to_str + @obj["owners"] end # Return the bot tags # @return [Array] def tags - @obj['tags'].to_str - end - - # Returns the bot banner url - # @return [String] - def bannerUrl - @obj['bannerUrl'].to_str + @obj["tags"] end - # Returns the donate bot guild ID - # @return [String] - def donatebotguildid - @obj['donatebotguildid'].to_str + # Returns an object containing the bot's reviews information. + # @return [Object] + def reviews + @obj["reviews"] end end end diff --git a/lib/topgg/botSearch.rb b/lib/topgg/botSearch.rb index 97b3ce8..060b193 100644 --- a/lib/topgg/botSearch.rb +++ b/lib/topgg/botSearch.rb @@ -10,7 +10,7 @@ def initialize(obj) # Get raw hash response # @return [Hash] attr_reader :obj - + alias raw obj alias data obj @@ -18,37 +18,49 @@ def initialize(obj) # The Total number of results # @return [Integer] def total - @obj['total'].to_i + @obj["total"].to_i end - # The first result - # @return [Spreader::Bot] + # The first result, can be nil + # @return [Bot] def first - Spreader::Bot.new(@obj['results'][0]) + results = @obj["results"] + + if results.empty? + nil + else + Bot.new(results[0]) + end end # The number of bots shown in the first page # @return [Integer] def count - @obj['count'].to_i + @obj["count"].to_i end - # Iterates through the results - # @return [Array] - def results - arr = [] - flag = 0 # iteration flag - @obj['results'].each do |data| - arr[flag] = Spreader::Bot.new(data) - flag += 1 + # The number of bots skipped, can be nil + # @return [Integer] + def offset + offset = @obj["offset"] + + if offset.nil? + nil + else + offset.to_i end - arr + end + + # Returns the results array + # @return [Array] + def results + @obj["results"].map { |b| Bot.new(b) } end # Length of the results. # @return [Integer] def size - @obj['results'].length + @obj["results"].length end end end diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb index 7504821..767c37e 100644 --- a/lib/topgg/stats.rb +++ b/lib/topgg/stats.rb @@ -9,26 +9,14 @@ def initialize(obj) # Returns raw Hash of the response attr_reader :obj - - alias raw obj + + alias raw obj alias data obj # Returns the server Count of the bot # @return [Integer] def server_count - @obj['server_count'] - end - - # The amount of servers per shard - # @return [Integer] - def shards - @obj['shards'] - end - - # Returns the total number of shards - # @return [Integer] - def shard_count - @obj['shard_count'] + @obj["server_count"] end end end diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index a5bf680..563db94 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -15,65 +15,23 @@ def initialize(obj) alias data obj # Check for errors, if any def error - @obj['error'] + @obj["error"] end # The Id of the user def id - @obj['id'] + @obj["id"] end # The username of the user def username - @obj['username'] + @obj["username"] end # The avatar of the user # @return [String] def avatar - "https://cdn.discordapp.com/avatars/#{@obj['id']}/#{@obj['avatar']}.webp?size=1024" - end - - # The default avatar of the user - # @return [String] - def defAvatar - @obj['defAvatar'] - end - - # Returns true/false depending upon if the user is a moderator or not. - # @return [Boolean] - def mod - @obj['mod'] - end - - # Returns true/false depending upon if the user is a supporter or not. - # @return [Boolean] - def supporter - @obj['supporter'] - end - - # Returns true/false depending upon if the user is a certified developer or not. - # @return [Boolean] - def certifiedDev - @obj['certifiedDev'] - end - - # Returns an object containing all user social integrations. - # @return [Object] - def social - @obj['social'] - end - - # Returns true/false depending on weather the user is an admin or not. - # @return [Boolean] - def admin - @obj['admin'] - end - - # Returns true/false depending on weather the user is a website Moderator or not. - # @return [Boolean] - def webMod - @obj['webMod'] + @obj["avatar"] end end end diff --git a/lib/topgg/utils/request.rb b/lib/topgg/utils/request.rb index 916910f..9c34823 100644 --- a/lib/topgg/utils/request.rb +++ b/lib/topgg/utils/request.rb @@ -1,43 +1,51 @@ -require 'net/http' -require 'json' - -module Dbl - module Utils - class Request - def initialize(token) - @token = token - @url = "https://top.gg/api" - end - - - def get(params) - - uri = URI.parse(@url+"/#{params}") +require "net/http" +require "json" + +module Dbl + module Utils + class Request + def initialize(token) + @token = token + @url = "https://top.gg/api" + end + + def get(params, query=nil) + uri = URI.parse(@url + "/#{params}") + + if not query.nil? + uri.query = URI.encode_www_form(query) + end + http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(uri.request_uri) - request.add_field 'Authorization', @token + request.add_field "Authorization", @token response = http.request(request) JSON.parse(response.body) - end - - def post(params, data) - + end - uri = URI.parse(@url+"/#{params}") - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE + def post(params, data) + uri = URI.parse(@url + "/#{params}") + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE - request = Net::HTTP::Post.new(uri.request_uri, initheader = {'Content-Type' =>'application/json', 'Authorization' => @token}) - request.body = data.to_json + request = + Net::HTTP::Post.new( + uri.request_uri, + initheader = { + "Content-Type" => "application/json", + "Authorization" => @token + } + ) + request.body = data.to_json - response = http.request(request) - JSON.parse(response.body) - end -end + response = http.request(request) + JSON.parse(response.body) + end + end + end end -end \ No newline at end of file diff --git a/lib/topgg/votes.rb b/lib/topgg/votes.rb index c44c0cd..739452f 100644 --- a/lib/topgg/votes.rb +++ b/lib/topgg/votes.rb @@ -10,14 +10,24 @@ def initialize(obj) # Get raw hash return of the object # @return [Hash] attr_reader :obj - + alias raw obj alias data obj - # Get the first vote amongst all the other votes. - # @return [Spreader::User] + # Get the first vote amongst all the other votes, can be nil + # @return [User] def first - Spreader::User.new(@obj[0]) + if @obj.empty? + nil + else + User.new(@obj[0]) + end + end + + # Returns the results array + # @return [Array] + def results + @obj.map { |u| User.new(u) } end # Get the total number of votes @@ -26,4 +36,4 @@ def total @obj.length end end -end \ No newline at end of file +end diff --git a/topgg.gemspec b/topgg.gemspec index 795f39d..c407586 100644 --- a/topgg.gemspec +++ b/topgg.gemspec @@ -1,31 +1,30 @@ # frozen_string_literal: true Gem::Specification.new do |spec| - spec.name = 'topgg' - spec.version = '1.1.0' - spec.authors = ['Adonis Tremblay'] - spec.email = ['rhydderchc@gmail.com'] + spec.name = "topgg" + spec.version = "1.1.0" + spec.authors = ["Adonis Tremblay"] + spec.email = ["rhydderchc@gmail.com"] - spec.summary = 'A top.gg api wrapper for ruby.' - spec.description = 'This is a ruby library of the top.gg API.' - spec.homepage = 'https://github.com/rhydderchc/topgg-ruby' - spec.license = 'MIT' - spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0') + spec.summary = "A top.gg api wrapper for ruby." + spec.description = "This is a ruby library of the top.gg API." + spec.homepage = "https://github.com/Top-gg-Community/ruby-sdk" + spec.license = "MIT" + spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") - spec.metadata['allowed_push_host'] = "https://rubygems.org" - - spec.metadata['homepage_uri'] = spec.homepage - spec.metadata['source_code_uri'] = 'https://github.com/rhydderchc/topgg-ruby' - spec.metadata['changelog_uri'] = 'https://github.com/rhydderchc/CHANGELOG.md' + spec.metadata["allowed_push_host"] = "https://rubygems.org" + spec.metadata["homepage_uri"] = spec.homepage # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path(__dir__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) } - end - spec.bindir = 'exe' - spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } - spec.require_paths = ['lib'] + spec.files = + Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0") + .reject { |f| f.match(%r{\A(?:test|spec|features)/}) } + end + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] # Uncomment to register a new dependency of your gem # spec.add_dependency "example-gem", "~> 1.0" From 39e43850b8a7d7da0fa593adbefaaefc40fddad6 Mon Sep 17 00:00:00 2001 From: null8626 Date: Mon, 16 Jun 2025 17:18:07 +0700 Subject: [PATCH 02/27] meta: update copyright year --- LICENSE | 2 +- LICENSE.txt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/LICENSE b/LICENSE index 0b78562..68561e0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 rhydderchc +Copyright (c) 2021-2025 rhydderchc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE.txt b/LICENSE.txt index 420b77e..68561e0 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2021 TODO: Write your name +Copyright (c) 2021-2025 rhydderchc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 3d1738158f8cede4f04be6e40e85de660ac43f4a Mon Sep 17 00:00:00 2001 From: null8626 Date: Mon, 16 Jun 2025 17:24:53 +0700 Subject: [PATCH 03/27] meta: bump version from 1.1.0 to 2.0.0 --- Gemfile.lock | 2 +- topgg.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 521f12b..a103733 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - topgg (1.1.0) + topgg (2.0.0) GEM remote: https://rubygems.org/ diff --git a/topgg.gemspec b/topgg.gemspec index c407586..4f0bc83 100644 --- a/topgg.gemspec +++ b/topgg.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "topgg" - spec.version = "1.1.0" + spec.version = "2.0.0" spec.authors = ["Adonis Tremblay"] spec.email = ["rhydderchc@gmail.com"] From ffb34f89b7a7a2a389576e6ad87977e01016a29a Mon Sep 17 00:00:00 2001 From: null8626 Date: Tue, 17 Jun 2025 15:40:50 +0700 Subject: [PATCH 04/27] feat: add widgets --- lib/lib.rb | 3 ++- lib/topgg/utils/request.rb | 2 +- lib/topgg/widget.rb | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 lib/topgg/widget.rb diff --git a/lib/lib.rb b/lib/lib.rb index 966c34f..9b49df3 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -7,6 +7,7 @@ require_relative "topgg/user" require_relative "topgg/stats" require_relative "topgg/votes" +require_relative "topgg/widget" # Class Topgg # The class instantiates all the methods for api requests and posts. @@ -37,7 +38,7 @@ def get_bots(params) # Get Bot statistics. # @return [Dbl::Stats] - def get_stats() + def get_stats Dbl::Stats.new(@request.get("bots/stats")) end diff --git a/lib/topgg/utils/request.rb b/lib/topgg/utils/request.rb index 9c34823..89e5e1a 100644 --- a/lib/topgg/utils/request.rb +++ b/lib/topgg/utils/request.rb @@ -6,7 +6,7 @@ module Utils class Request def initialize(token) @token = token - @url = "https://top.gg/api" + @url = "https://top.gg/api/v1" end def get(params, query=nil) diff --git a/lib/topgg/widget.rb b/lib/topgg/widget.rb new file mode 100644 index 0000000..5d4e823 --- /dev/null +++ b/lib/topgg/widget.rb @@ -0,0 +1,16 @@ +module Dbl + # Widget generator functions. + class Widget + @base_url = "https://top.gg/api/v1" + + class << self + attr_accessor :base_url + + # Generates a large widget URL. + # @param id [String] The ID. + def large(id) + "#{@base_url}/widgets/large/#{id}" + end + end + end +end \ No newline at end of file From e4acb299d71cf52fc2da82d2a30b945e8b3faf01 Mon Sep 17 00:00:00 2001 From: null8626 Date: Wed, 18 Jun 2025 20:46:09 +0700 Subject: [PATCH 05/27] feat: add small widgets --- lib/topgg/widget.rb | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/topgg/widget.rb b/lib/topgg/widget.rb index 5d4e823..6268083 100644 --- a/lib/topgg/widget.rb +++ b/lib/topgg/widget.rb @@ -5,11 +5,47 @@ class Widget class << self attr_accessor :base_url + + TYPES = [:discord_bot, :discord_server] # Generates a large widget URL. + # @param ty [Symbol] The widget type. + # @param id [String] The ID. + def large(ty, id) + raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) + type = ty.to_s.gsub('_', '/') + + "#{@base_url}/widgets/large/#{type}/#{id}" + end + + # Generates a small widget URL for displaying votes. + # @param ty [Symbol] The widget type. + # @param id [String] The ID. + def votes(ty, id) + raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) + type = ty.to_s.gsub('_', '/') + + "#{@base_url}/widgets/small/votes/#{type}/#{id}" + end + + # Generates a small widget URL for displaying an entity's owner. + # @param ty [Symbol] The widget type. + # @param id [String] The ID. + def owner(ty, id) + raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) + type = ty.to_s.gsub('_', '/') + + "#{@base_url}/widgets/small/owner/#{type}/#{id}" + end + + # Generates a small widget URL for displaying social stats. + # @param ty [Symbol] The widget type. # @param id [String] The ID. - def large(id) - "#{@base_url}/widgets/large/#{id}" + def social(ty, id) + raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) + type = ty.to_s.gsub('_', '/') + + "#{@base_url}/widgets/small/social/#{type}/#{id}" end end end From e18a03ac26238919fce7bfee6f904ff5e54f0468 Mon Sep 17 00:00:00 2001 From: null8626 Date: Mon, 23 Jun 2025 23:37:59 +0700 Subject: [PATCH 06/27] docs: readme overhaul --- README.md | 127 +++++++++++++++++++++++++++++++++----------- lib/lib.rb | 22 ++++++-- lib/topgg/widget.rb | 2 +- 3 files changed, 115 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 9ec3aad..164e73a 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,126 @@ -# [Top.gg](https://top.gg) Ruby +# Top.gg Ruby SDK -The Top.gg Ruby SDK is a lighweight package, that allows you -to fetch data from the top.gg api and post data such as statistics to the website. +The community-maintained Ruby library for Top.gg. -It provides you with numerous methods to interact with the API. +## Installation -## Dependencies +```sh +$ gem install topgg +``` -- Ruby +## Setting up -## Installation +```rb +require "topgg" + +client = Topgg.new(ENV["TOPGG_TOKEN"]) +``` -```bash +## Usage -gem install topgg +### Getting a bot +```rb +bot = client.get_bot("264811613708746752") ``` -## Note +### Getting several bots -You require a Token to interact with the Api. -The token can be found at `https://top.gg/bot/[YOUR_BOT_ID]/webhooks` +```rb +bots = client.get_bots({ sort: "date", limit: 50, offset: 0 }) -## Example +for bot in bots.results do + puts bot.username +end +``` -Here's a straightforward example of how to request data with the wrapper. +### Getting your bot's voters -```ruby -require "topgg" +#### First page + +```rb +voters = client.get_votes -client = Topgg.new("AUTH_TOKEN", "BOTID") +for voter in voters.results do + puts voter.username +end +``` + +#### Subsequent pages + +```rb +voters = client.get_votes(2) + +for voter in voters.results do + puts voter.username +end +``` + +### Check if a user has voted for your bot -client.get_bot("1234").avatar -# returns -# "https://cdn.discordapp.com/avatars/661200758510977084/4354318859c319c7ca39753260fdd350.png?size=4096" +```rb +has_voted = client.voted?("661200758510977084") ``` -### Auto Posting +### Getting your bot's server count -The library provides you with autoposting functionality, and autoposts at an interval of 15 minutes. -Here's how you can use it +```rb +stats = client.get_stats +server_count = client.server_count +``` -```ruby -require "topgg" +### Posting your bot's server count + +```rb +client.post_stats(bot.server_count) +``` + +### Automatically posting your bot's server count every few minutes + +For Discordrb: + +```rb require "discordrb" -bot = Discordrb::Bot.new token: "TOKEN" +bot = Discordrb::Bot.new(token: env["BOT_TOKEN"], intents: [:servers]) -client = Topgg.new("AUTH_TOKEN", "BOTID") bot.ready do |event| - client.auto_post_stats(bot) # The discordrb bot client. + client.auto_post_stats(bot) + + puts "Bot is now ready!" end + bot.run ``` -# Documentation +### Checking if the weekend vote multiplier is active + +```rb +is_weekend = client.is_weekend? +``` + +### Generating widget URLs + +#### Large + +```rb +widget_url = Dbl::Widget.large(:discord_bot, "574652751745777665") +``` + +#### Votes + +```rb +widget_url = Dbl::Widget.votes(:discord_bot, "574652751745777665") +``` + +#### Owner + +```rb +widget_url = Dbl::Widget.owner(:discord_bot, "574652751745777665") +``` + +#### Social -Check out the api reference [here](https://rubydoc.info/gems/topgg/) +```rb +widget_url = Dbl::Widget.social(:discord_bot, "574652751745777665") +``` \ No newline at end of file diff --git a/lib/lib.rb b/lib/lib.rb index 9b49df3..7936e68 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true -require_relative "topgg/utils/request" +require "base64" require "json" + +require_relative "topgg/utils/request" require_relative "topgg/bot" require_relative "topgg/botSearch" require_relative "topgg/user" @@ -14,9 +16,19 @@ class Topgg # initializes the class attributes. # @param token [String] The authorization token from top.gg - # @param id [String] The client id of the bot. - def initialize(token, id) - @id = id + def initialize(token) + begin + token_section = token.split('.')[1] + padding = '=' * ((4 - token_section.length % 4) % 4) + token_section += padding + + token_data = JSON.parse(Base64.decode64(token_section)) + + @id = token_data['id'] + rescue StandardError + raise ArgumentError, 'Got a malformed API token.' + end + @token = token @request = Dbl::Utils::Request.new(token) end @@ -60,7 +72,7 @@ def is_weekend? # Get the last 1000 unique votes of the bot(self) # @param page [Integer] The page to use. Defaults to 1. # @return [Dbl::Votes] - def votes(page = 1) + def get_votes(page = 1) page = 1 if page.to_i < 1 resp = @request.get("bots/#{@id}/votes", { page: page }) diff --git a/lib/topgg/widget.rb b/lib/topgg/widget.rb index 6268083..089fa52 100644 --- a/lib/topgg/widget.rb +++ b/lib/topgg/widget.rb @@ -21,7 +21,7 @@ def large(ty, id) # Generates a small widget URL for displaying votes. # @param ty [Symbol] The widget type. # @param id [String] The ID. - def votes(ty, id) + def get_votes(ty, id) raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) type = ty.to_s.gsub('_', '/') From 3d00aabd5dd6d97d7f47af928eee15d3ca2a43a6 Mon Sep 17 00:00:00 2001 From: null8626 Date: Thu, 26 Jun 2025 20:34:03 +0700 Subject: [PATCH 07/27] feat: add webhooks --- Gemfile | 6 ++++-- Gemfile.lock | 15 +++++++------ README.md | 36 ++++++++++++++++++++++++++++++- lib/{lib.rb => topgg.rb} | 3 ++- lib/topgg/bot.rb | 5 +++-- lib/topgg/botSearch.rb | 2 +- lib/topgg/stats.rb | 5 +++-- lib/topgg/user.rb | 4 +++- lib/topgg/vote.rb | 46 ++++++++++++++++++++++++++++++++++++++++ lib/topgg/webhooks.rb | 45 +++++++++++++++++++++++++++++++++++++++ topgg.gemspec | 8 +------ 11 files changed, 151 insertions(+), 24 deletions(-) rename lib/{lib.rb => topgg.rb} (98%) create mode 100644 lib/topgg/vote.rb create mode 100644 lib/topgg/webhooks.rb diff --git a/Gemfile b/Gemfile index 9390882..ed050f9 100644 --- a/Gemfile +++ b/Gemfile @@ -5,5 +5,7 @@ source "https://rubygems.org" # Specify your gem's dependencies in topgg.gemspec gemspec -gem "rake", "~> 13.0" -gem "ostruct", "~> 0.6" +gem "rack" +gem "rake" +gem "ostruct" +gem "cgi" diff --git a/Gemfile.lock b/Gemfile.lock index a103733..87ef933 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,25 +2,26 @@ PATH remote: . specs: topgg (2.0.0) + rack (~> 3.0.9.1) GEM remote: https://rubygems.org/ specs: + cgi (0.5.0) ostruct (0.6.1) - power_assert (2.0.5) + rack (3.0.9.1) rake (13.0.6) - test-unit (3.6.8) - power_assert PLATFORMS x64-mingw-ucrt x86_64-linux DEPENDENCIES - ostruct (~> 0.6) - rake (~> 13.0) - test-unit (~> 3.1, >= 3.1.8) + cgi (~> 0.5.0) + ostruct + rack + rake topgg! BUNDLED WITH - 2.6.7 + 2.6.9 diff --git a/README.md b/README.md index 164e73a..375f8d2 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ has_voted = client.voted?("661200758510977084") ```rb stats = client.get_stats -server_count = client.server_count +server_count = stats.server_count ``` ### Posting your bot's server count @@ -123,4 +123,38 @@ widget_url = Dbl::Widget.owner(:discord_bot, "574652751745777665") ```rb widget_url = Dbl::Widget.social(:discord_bot, "574652751745777665") +``` + +### Webhooks + +#### Being notified whenever someone voted for your bot + +##### Ruby on Rails + +In your `config/application.rb`: + +```rb +module MyServer + class Application < Rails::Application + # ... + + config.middleware.use Dbl::Webhook, + type: Dbl::Webhook::VOTE, + path: "/votes", + auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| + Rails.logger.info "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" + end + end +end +``` + +##### Sinatra + +```rb +use Dbl::Webhook, +type: Dbl::Webhook::VOTE, +path: "/votes", +auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| + puts "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" +end ``` \ No newline at end of file diff --git a/lib/lib.rb b/lib/topgg.rb similarity index 98% rename from lib/lib.rb rename to lib/topgg.rb index 7936e68..de44c9a 100644 --- a/lib/lib.rb +++ b/lib/topgg.rb @@ -3,12 +3,13 @@ require "base64" require "json" -require_relative "topgg/utils/request" require_relative "topgg/bot" require_relative "topgg/botSearch" require_relative "topgg/user" require_relative "topgg/stats" +require_relative "topgg/vote" require_relative "topgg/votes" +require_relative "topgg/webhooks" require_relative "topgg/widget" # Class Topgg diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index b866cb2..58060fe 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -1,4 +1,4 @@ -require "Date" +require "date" module Dbl # The Bot class spreads the json parsed hash into different methods @@ -8,13 +8,14 @@ class Bot def initialize(obj) @obj = obj end + # Returns raw hash of the parsed json object # @return [Hash] attr_reader :obj alias raw obj - alias data obj + # Returns error message if there's an error, otherwise nil # @return [String] def error diff --git a/lib/topgg/botSearch.rb b/lib/topgg/botSearch.rb index 060b193..43d2225 100644 --- a/lib/topgg/botSearch.rb +++ b/lib/topgg/botSearch.rb @@ -7,12 +7,12 @@ class BotSearch def initialize(obj) @obj = obj end + # Get raw hash response # @return [Hash] attr_reader :obj alias raw obj - alias data obj # The Total number of results diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb index 767c37e..c22354d 100644 --- a/lib/topgg/stats.rb +++ b/lib/topgg/stats.rb @@ -7,12 +7,13 @@ def initialize(obj) @obj = obj end - # Returns raw Hash of the response + # Get raw hash response + # @return [Hash] attr_reader :obj alias raw obj - alias data obj + # Returns the server Count of the bot # @return [Integer] def server_count diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index 563db94..d8463e8 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -8,11 +8,13 @@ def initialize(obj) @obj = obj end + # Get raw hash response + # @return [Hash] attr_reader :obj alias raw obj - alias data obj + # Check for errors, if any def error @obj["error"] diff --git a/lib/topgg/vote.rb b/lib/topgg/vote.rb new file mode 100644 index 0000000..db8c69d --- /dev/null +++ b/lib/topgg/vote.rb @@ -0,0 +1,46 @@ +module Dbl + class Vote + def initialize(obj) + @obj = obj + end + + # Returns raw hash of the parsed json object + # @return [Hash] + attr_reader :obj + + alias raw obj + alias data obj + + # Returns the ID of the Discord bot/server that received a vote. + # @return [String] + def receiver_id + !@obj["bot"].nil? ? @obj["guild"] : @obj["bot"] + end + + # Returns the ID of the Top.gg user who voted. + # @return [String] + def voter_id + @obj["user"] + end + + # Returns whether this vote is just a test done from the page settings. + # @return [Boolean] + def is_test + @obj["type"] == "test" + end + + # Returns whether the weekend multiplier is active, where a single vote counts as two. + # @return [Boolean] + def is_weekend + @obj["isWeekend"] == true + end + + # Returns query strings found on the vote page. + # @return [Hash] + def query + return nil if @obj["query"].nil? + + CGI.parse(@obj["query"]).transform_values(&:first) + end + end +end \ No newline at end of file diff --git a/lib/topgg/webhooks.rb b/lib/topgg/webhooks.rb new file mode 100644 index 0000000..dc7f6b8 --- /dev/null +++ b/lib/topgg/webhooks.rb @@ -0,0 +1,45 @@ +require "rack" +require "cgi" + +require_relative "vote" + +module Dbl + class Webhook + VOTE = ->(json) { Vote.new(json) } + + def initialize(app, type:, path:, auth:, &callback) + raise ArgumentError, "A callback must be provided" unless callback + raise ArgumentError, "A type must be provided" unless type.respond_to?(:call) + + @app = app + @deserializer = type + @path = path + @auth = auth + @callback = callback + end + + def call(env) + req = Rack::Request.new(env) + + if req.post? && req.path.start_with?(@path) + if req.get_header('HTTP_AUTHORIZATION') != @auth + return [401, { 'Content-Type' => 'text/plain' }, ['Unauthorized']] + end + + body = req.body.read + + begin + data = JSON.parse(body) + + @callback.call(@deserializer.call(data)) if data + + return [204, { 'Content-Type' => 'text/plain' }, ['']] + rescue JSON::ParserError + return [400, { 'Content-Type' => 'text/plain' }, ['Bad request']] + end + end + + @app.call(env) + end + end +end \ No newline at end of file diff --git a/topgg.gemspec b/topgg.gemspec index 4f0bc83..9f59e0a 100644 --- a/topgg.gemspec +++ b/topgg.gemspec @@ -15,13 +15,7 @@ Gem::Specification.new do |spec| spec.metadata["allowed_push_host"] = "https://rubygems.org" spec.metadata["homepage_uri"] = spec.homepage - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = - Dir.chdir(File.expand_path(__dir__)) do - `git ls-files -z`.split("\x0") - .reject { |f| f.match(%r{\A(?:test|spec|features)/}) } - end + spec.files = Dir.glob("lib/**/*") spec.bindir = "exe" spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] From beb754e245262538231861b1e2da89d89dd5daf4 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 4 Jul 2025 21:13:20 +0700 Subject: [PATCH 08/27] feat: rename stats methods --- README.md | 5 ++--- lib/topgg.rb | 13 +++++++------ lib/topgg/stats.rb | 23 ----------------------- 3 files changed, 9 insertions(+), 32 deletions(-) delete mode 100644 lib/topgg/stats.rb diff --git a/README.md b/README.md index 375f8d2..562f69c 100644 --- a/README.md +++ b/README.md @@ -65,14 +65,13 @@ has_voted = client.voted?("661200758510977084") ### Getting your bot's server count ```rb -stats = client.get_stats -server_count = stats.server_count +server_count = client.get_server_count ``` ### Posting your bot's server count ```rb -client.post_stats(bot.server_count) +client.post_server_count(bot.server_count) ``` ### Automatically posting your bot's server count every few minutes diff --git a/lib/topgg.rb b/lib/topgg.rb index de44c9a..4d57e0f 100644 --- a/lib/topgg.rb +++ b/lib/topgg.rb @@ -49,10 +49,11 @@ def get_bots(params) Dbl::BotSearch.new(@request.get("bots", params)) end - # Get Bot statistics. - # @return [Dbl::Stats] - def get_stats - Dbl::Stats.new(@request.get("bots/stats")) + # The method fetches your Discord bot's posted server count. + # @return [Integer] + def get_server_count + resp = @request.get("bots/stats") + resp["server_count"] end # Mini-method to query if the bot(self) was voted by the user. @@ -80,9 +81,9 @@ def get_votes(page = 1) Dbl::Votes.new(resp) end - # Post Bot Statistics to the website + # The method posts your Discord bot's server count to the API. This will update the server count in your bot's Top.gg page. # @param server_count [Integer] The amount of servers the bot is in. Must not be less than 1. - def post_stats(server_count) + def post_server_count(server_count) raise ArgumentError, "server_count cannot be less than 1" unless server_count > 0 json_post = { server_count: server_count }.to_json diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb deleted file mode 100644 index c22354d..0000000 --- a/lib/topgg/stats.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Dbl - # The Stats class spreads the json response into different methods - class Stats - # Initializes the Stats class - # @param obj [Object] Response Hash - def initialize(obj) - @obj = obj - end - - # Get raw hash response - # @return [Hash] - attr_reader :obj - - alias raw obj - alias data obj - - # Returns the server Count of the bot - # @return [Integer] - def server_count - @obj["server_count"] - end - end -end From eb3cdf36d07457fa921f3bf053494891fe5ed5cf Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 4 Jul 2025 21:20:53 +0700 Subject: [PATCH 09/27] feat: rename methods --- README.md | 4 ++-- lib/topgg.rb | 4 ++-- lib/topgg/widget.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 562f69c..19935aa 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ end #### First page ```rb -voters = client.get_votes +voters = client.get_voters for voter in voters.results do puts voter.username @@ -49,7 +49,7 @@ end #### Subsequent pages ```rb -voters = client.get_votes(2) +voters = client.get_voters(2) for voter in voters.results do puts voter.username diff --git a/lib/topgg.rb b/lib/topgg.rb index 4d57e0f..b2659b8 100644 --- a/lib/topgg.rb +++ b/lib/topgg.rb @@ -6,11 +6,11 @@ require_relative "topgg/bot" require_relative "topgg/botSearch" require_relative "topgg/user" -require_relative "topgg/stats" require_relative "topgg/vote" require_relative "topgg/votes" require_relative "topgg/webhooks" require_relative "topgg/widget" +require_relative "topgg/utils/request" # Class Topgg # The class instantiates all the methods for api requests and posts. @@ -101,7 +101,7 @@ def auto_post_stats(client) semaphore.synchronize do interval 900 do server_len = client.servers.length - post_stats(server_len) + post_server_count(server_len) puts( "[TOPGG] : \033[31;1;4m Bot statistics has been successfully posted!\033[0m" ) diff --git a/lib/topgg/widget.rb b/lib/topgg/widget.rb index 089fa52..6268083 100644 --- a/lib/topgg/widget.rb +++ b/lib/topgg/widget.rb @@ -21,7 +21,7 @@ def large(ty, id) # Generates a small widget URL for displaying votes. # @param ty [Symbol] The widget type. # @param id [String] The ID. - def get_votes(ty, id) + def votes(ty, id) raise ArgumentError, "Invalid widget type" unless TYPES.include?(ty) type = ty.to_s.gsub('_', '/') From 7851039a1423dd6c0aeb1cd5b967343e0074bb50 Mon Sep 17 00:00:00 2001 From: null8626 Date: Sat, 19 Jul 2025 19:51:35 +0700 Subject: [PATCH 10/27] doc: add chapters --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 19935aa..2997976 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,23 @@ The community-maintained Ruby library for Top.gg. +## Chapters + +- [Installation](#installation) +- [Setting up](#setting-up) +- [Usage](#usage) + - [Getting a bot](#getting-a-bot) + - [Getting several bots](#getting-several-bots) + - [Getting your bot's voters](#getting-your-bots-voters) + - [Check if a user has voted for your bot](#check-if-a-user-has-voted-for-your-bot) + - [Getting your bot's server count](#getting-your-bots-server-count) + - [Posting your bot's server count](#posting-your-bots-server-count) + - [Automatically posting your bot's server count every few minutes](#automatically-posting-your-bots-server-count-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 bot](#being-notified-whenever-someone-voted-for-your-bot) + ## Installation ```sh From b2b4d503ac7e9c42cb398293f713a9cb2608ad7f Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 00:20:40 +0700 Subject: [PATCH 11/27] feat: proceed with the breaking changes (temporary) --- lib/topgg.rb | 10 +++++----- lib/topgg/bot.rb | 2 +- lib/topgg/utils/request.rb | 4 ++-- lib/topgg/vote.rb | 2 +- lib/topgg/widget.rb | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/topgg.rb b/lib/topgg.rb index b2659b8..61b22aa 100644 --- a/lib/topgg.rb +++ b/lib/topgg.rb @@ -51,12 +51,12 @@ def get_bots(params) # The method fetches your Discord bot's posted server count. # @return [Integer] - def get_server_count + def get_bot_server_count resp = @request.get("bots/stats") resp["server_count"] end - # Mini-method to query if the bot(self) was voted by the user. + # Mini-method to query if the project (self) was voted by the user in the past 12 hours. # @param userid [String] The user id. # @return [Boolean] def voted?(userid) @@ -71,7 +71,7 @@ def is_weekend? resp["is_weekend"] end - # Get the last 1000 unique votes of the bot(self) + # Get the unique votes of the project (self) # @param page [Integer] The page to use. Defaults to 1. # @return [Dbl::Votes] def get_votes(page = 1) @@ -83,7 +83,7 @@ def get_votes(page = 1) # The method posts your Discord bot's server count to the API. This will update the server count in your bot's Top.gg page. # @param server_count [Integer] The amount of servers the bot is in. Must not be less than 1. - def post_server_count(server_count) + def post_bot_server_count(server_count) raise ArgumentError, "server_count cannot be less than 1" unless server_count > 0 json_post = { server_count: server_count }.to_json @@ -101,7 +101,7 @@ def auto_post_stats(client) semaphore.synchronize do interval 900 do server_len = client.servers.length - post_server_count(server_len) + post_bot_server_count(server_len) puts( "[TOPGG] : \033[31;1;4m Bot statistics has been successfully posted!\033[0m" ) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 58060fe..05d7908 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -130,7 +130,7 @@ def tags @obj["tags"] end - # Returns an object containing the bot's reviews information. + # Returns an object containing the bot's review information. # @return [Object] def reviews @obj["reviews"] diff --git a/lib/topgg/utils/request.rb b/lib/topgg/utils/request.rb index 89e5e1a..db191db 100644 --- a/lib/topgg/utils/request.rb +++ b/lib/topgg/utils/request.rb @@ -6,7 +6,7 @@ module Utils class Request def initialize(token) @token = token - @url = "https://top.gg/api/v1" + @url = "https://top.gg/api" end def get(params, query=nil) @@ -21,7 +21,7 @@ def get(params, query=nil) http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(uri.request_uri) - request.add_field "Authorization", @token + request.add_field "Authorization", "Bearer #{@token}" response = http.request(request) JSON.parse(response.body) diff --git a/lib/topgg/vote.rb b/lib/topgg/vote.rb index db8c69d..14c8e62 100644 --- a/lib/topgg/vote.rb +++ b/lib/topgg/vote.rb @@ -11,7 +11,7 @@ def initialize(obj) alias raw obj alias data obj - # Returns the ID of the Discord bot/server that received a vote. + # Returns the ID of the project that received a vote. # @return [String] def receiver_id !@obj["bot"].nil? ? @obj["guild"] : @obj["bot"] diff --git a/lib/topgg/widget.rb b/lib/topgg/widget.rb index 6268083..830e8c5 100644 --- a/lib/topgg/widget.rb +++ b/lib/topgg/widget.rb @@ -28,7 +28,7 @@ def votes(ty, id) "#{@base_url}/widgets/small/votes/#{type}/#{id}" end - # Generates a small widget URL for displaying an entity's owner. + # Generates a small widget URL for displaying a project's owner. # @param ty [Symbol] The widget type. # @param id [String] The ID. def owner(ty, id) From 7185abbbffc8e651fd6de0eee949bef7be81cb8e Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 00:30:01 +0700 Subject: [PATCH 12/27] revert: revert breaking changes (part 1) --- lib/topgg/stats.rb | 34 ++++++++++++++++++++++++++++++++++ lib/topgg/user.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 lib/topgg/stats.rb diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb new file mode 100644 index 0000000..f832b6c --- /dev/null +++ b/lib/topgg/stats.rb @@ -0,0 +1,34 @@ +module Dbl + # The Stats class spreads the JSON response into different methods + class Stats + # Initializes the Stats class + # @param obj [Object] Response Hash + def initialize(obj) + @obj = obj + end + + # Returns raw Hash of the response + attr_reader :obj + + alias raw obj + + alias data obj + # The bot's server count + # @return [Integer] + def server_count + @obj['server_count'] + end + + # The bot's server count in each shard + # @return [Integer] + def shards + @obj['shards'] + end + + # The bot's shard count + # @return [Integer] + def shard_count + @obj['shard_count'] + end + end +end \ No newline at end of file diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index d8463e8..d6a1a61 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -35,5 +35,46 @@ def username def avatar @obj["avatar"] end + + # The default avatar of the user + # @return [String] + def defAvatar + "" + end + + # Whether the user is a moderator. + # @return [Boolean] + def mod + false + end + + # Whether the user is a Top.gg supporter. + # @return [Boolean] + def supporter + false + end + + # Whether the user is a certified developer. + # @return [Boolean] + def certifiedDev + false + end + + # The user's socials + # @return [Object] + def social + nil + end + + # Whether the user is an administrator. + # @return [Boolean] + def admin + false + end + + # Whether the user is a web moderator. + # @return [Boolean] + def webMod + false end end From 97552552ac32fe7d21ecfc36c07f02fead9790bf Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 00:35:40 +0700 Subject: [PATCH 13/27] [doc,fix]: better documentation, fix bearer prefix inconsistency --- lib/topgg/bot.rb | 2 +- lib/topgg/botSearch.rb | 2 +- lib/topgg/stats.rb | 2 +- lib/topgg/user.rb | 2 +- lib/topgg/utils/request.rb | 2 +- lib/topgg/vote.rb | 1 + lib/topgg/votes.rb | 2 +- lib/topgg/webhooks.rb | 1 + 8 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 05d7908..f46ef89 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -1,7 +1,7 @@ require "date" module Dbl - # The Bot class spreads the json parsed hash into different methods + # A Discord bot listed on Top.gg class Bot # Initializes the Bot class # @param obj [Object] diff --git a/lib/topgg/botSearch.rb b/lib/topgg/botSearch.rb index 43d2225..31b99b3 100644 --- a/lib/topgg/botSearch.rb +++ b/lib/topgg/botSearch.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true module Dbl - # This class spreads the BotSearch Response body into different methods + # A Discord bot search query class BotSearch # Initalizes the BotSearch class # @param obj [Object] Response Hash diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb index f832b6c..4bfba05 100644 --- a/lib/topgg/stats.rb +++ b/lib/topgg/stats.rb @@ -1,5 +1,5 @@ module Dbl - # The Stats class spreads the JSON response into different methods + # A Discord bot's statistics class Stats # Initializes the Stats class # @param obj [Object] Response Hash diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index d6a1a61..0e6338d 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true module Dbl - # The User class, used for Spreading the response body into different methods + # A Top.gg user class User # Instantiates the class variables # @param obj [Object] Response Data Object diff --git a/lib/topgg/utils/request.rb b/lib/topgg/utils/request.rb index db191db..4add0f4 100644 --- a/lib/topgg/utils/request.rb +++ b/lib/topgg/utils/request.rb @@ -38,7 +38,7 @@ def post(params, data) uri.request_uri, initheader = { "Content-Type" => "application/json", - "Authorization" => @token + "Authorization" => "Bearer #{@token}" } ) request.body = data.to_json diff --git a/lib/topgg/vote.rb b/lib/topgg/vote.rb index 14c8e62..7b630d3 100644 --- a/lib/topgg/vote.rb +++ b/lib/topgg/vote.rb @@ -1,4 +1,5 @@ module Dbl + # A dispatched Top.gg vote event class Vote def initialize(obj) @obj = obj diff --git a/lib/topgg/votes.rb b/lib/topgg/votes.rb index 739452f..59d2f0c 100644 --- a/lib/topgg/votes.rb +++ b/lib/topgg/votes.rb @@ -1,5 +1,5 @@ module Dbl - # This class Spreads the Vote response body into different methods. + # A collection of Top.gg votes class Votes # Initializes the votes class # @param obj [Object] JSON parsed object diff --git a/lib/topgg/webhooks.rb b/lib/topgg/webhooks.rb index dc7f6b8..4ec9f47 100644 --- a/lib/topgg/webhooks.rb +++ b/lib/topgg/webhooks.rb @@ -4,6 +4,7 @@ require_relative "vote" module Dbl + # A wrapper for directly receiving events from Top.gg's servers class Webhook VOTE = ->(json) { Vote.new(json) } From 7743947f774ca0862393d8bc90c0c72a88586c17 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 00:37:11 +0700 Subject: [PATCH 14/27] meta: change the latest version from 2.0.0 to 1.2.0 --- Gemfile.lock | 2 +- topgg.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 87ef933..0d073fd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - topgg (2.0.0) + topgg (1.2.0) rack (~> 3.0.9.1) GEM diff --git a/topgg.gemspec b/topgg.gemspec index 9f59e0a..8fe4670 100644 --- a/topgg.gemspec +++ b/topgg.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "topgg" - spec.version = "2.0.0" + spec.version = "1.2.0" spec.authors = ["Adonis Tremblay"] spec.email = ["rhydderchc@gmail.com"] From 881566c028ce114d4d8d6b9250f1bfdd0f5602c4 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 00:39:14 +0700 Subject: [PATCH 15/27] revert: revert renaming of lib.rb to topgg.rb --- lib/{topgg.rb => lib.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/{topgg.rb => lib.rb} (100%) diff --git a/lib/topgg.rb b/lib/lib.rb similarity index 100% rename from lib/topgg.rb rename to lib/lib.rb From 9ede331872d431d49e568b2dc3847907702f289d Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:15:28 +0700 Subject: [PATCH 16/27] [doc,revert]: improve documentation, revert breaking changes --- lib/lib.rb | 45 ++++++++++++++++++++++++--------------- lib/topgg/bot.rb | 48 ++++++++++++++++++++++++------------------ lib/topgg/botSearch.rb | 6 +++--- lib/topgg/stats.rb | 3 ++- lib/topgg/user.rb | 10 ++++----- lib/topgg/vote.rb | 12 +++++------ lib/topgg/votes.rb | 4 ++-- topgg.gemspec | 4 ++-- 8 files changed, 75 insertions(+), 57 deletions(-) diff --git a/lib/lib.rb b/lib/lib.rb index 61b22aa..a71b85e 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -13,7 +13,7 @@ require_relative "topgg/utils/request" # Class Topgg -# The class instantiates all the methods for api requests and posts. +# The class instantiates all the methods for API requests and posts. class Topgg # initializes the class attributes. # @param token [String] The authorization token from top.gg @@ -34,30 +34,39 @@ def initialize(token) @request = Dbl::Utils::Request.new(token) end - # The method fetches bot statistics from top.gg - # @param id [String] The id of the bot you want to fetch statistics from. + # Fetches bot statistics from top.gg + # @param id [String] The bot's ID # @return [Dbl::Bot] The Bot Object def get_bot(id) Dbl::Bot.new(@request.get("bots/#{id}")) end - # The method searches bots from top.gg using a keyword query. + # Searches bots from Top.gg using a keyword query. # @param [Object] params The parameters that can be used to query a search # To know what the parameters are check it out here # @return [Dbl::BotSearch] The BotSearch Object - def get_bots(params) + def search_bot(params) Dbl::BotSearch.new(@request.get("bots", params)) end - # The method fetches your Discord bot's posted server count. - # @return [Integer] - def get_bot_server_count + # [Deprecated] Fetch a user on Top.gg based on an ID + # @param id [String] The user's ID + # @return [Dbl::User] + def user(id) + nil + end + + # Get your Discord bot's posted statistics + # @param id [String] The bot's ID. Unused, no longer has an effect. + # @return [Dbl::Stats] + def get_stats(id = nil) resp = @request.get("bots/stats") - resp["server_count"] + + Dbl::Stats.new(resp) end - # Mini-method to query if the project (self) was voted by the user in the past 12 hours. - # @param userid [String] The user id. + # Mini-method to query if your project was voted by the user in the past 12 hours. + # @param userid [String] The user's ID. # @return [Boolean] def voted?(userid) resp = @request.get("bots/check", { userId: userid }) @@ -71,19 +80,21 @@ def is_weekend? resp["is_weekend"] end - # Get the unique votes of the project (self) + # Get the unique votes of your project # @param page [Integer] The page to use. Defaults to 1. # @return [Dbl::Votes] - def get_votes(page = 1) + def votes(page = 1) page = 1 if page.to_i < 1 resp = @request.get("bots/#{@id}/votes", { page: page }) Dbl::Votes.new(resp) end - # The method posts your Discord bot's server count to the API. This will update the server count in your bot's Top.gg page. + # Posts your Discord bot's server count to the API. This will update the server count in your bot's Top.gg page. # @param server_count [Integer] The amount of servers the bot is in. Must not be less than 1. - def post_bot_server_count(server_count) + # @param shards [Integer] The amount of servers the bot is in per shard. Unused, no longer has an effect. + # @param shard_count [Integer] The total number of shards. Unused, no longer has an effect. + def post_stats(server_count, shards = nil, shard_count = nil) raise ArgumentError, "server_count cannot be less than 1" unless server_count > 0 json_post = { server_count: server_count }.to_json @@ -93,7 +104,7 @@ def post_bot_server_count(server_count) ) end - # Auto-posts stats on to the top.gg website + # Auto-posts stats to the Top.gg website # @param client [Discordrb::Bot] instanceof discordrb client. def auto_post_stats(client) semaphore = Mutex.new @@ -101,7 +112,7 @@ def auto_post_stats(client) semaphore.synchronize do interval 900 do server_len = client.servers.length - post_bot_server_count(server_len) + post_stats(server_len) puts( "[TOPGG] : \033[31;1;4m Bot statistics has been successfully posted!\033[0m" ) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index f46ef89..d089fb1 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -9,128 +9,134 @@ def initialize(obj) @obj = obj end - # Returns raw hash of the parsed json object + # The raw hash of the parsed JSON object # @return [Hash] attr_reader :obj alias raw obj alias data obj - # Returns error message if there's an error, otherwise nil + # The bot's default avatar + # @return [String] + def defAvatar + "" + end + + # The error message if there's an error, otherwise nil # @return [String] def error @obj["error"] end - # Returns the invite link of the bot + # The bot's invite URL # @return [String] def invite @obj["invite"] end - # Returns the bot website, if configured + # The bot's website URL, if configured # @return [String] def website @obj["website"] end - # Returns support server link + # The bot's support server URL # @return [String] def support @obj["support"] end - # Returns github repository link, if any + # The bot's github repository URL, if any # @return [String] def github @obj["github"] end - # Returns the long Description of the bot + # The bot's long description # @return [String] def longdesc @obj["longdesc"] end - # Returns the short description of the bot + # The bot's short description # @return [String] def shortdesc @obj["shortdesc"] end - # Returns the default prefix of the bot + # The bot's default prefix # @return [String] def prefix @obj["prefix"] end - # Returns the bot client id + # The bot's client ID # @return [String] def clientid @obj["clientid"] end - # Returns the avatar link of the bot + # The bot's avatar URL # @return [String] def avatar @obj["avatar"] end - # Returns the bot id + # The bot's ID # @return [String] def id @obj["id"] end - # Returns the bot username + # The bot's username # @return [String] def username @obj["username"] end - # Returns the date on which the bot was submitted + # The bot's submission date # @return [Date] def date Date.parse(@obj["date"]) end - # Returns the server count of the bot + # The bot's posted server count # @return [Integer] def server_count @obj["server_count"].to_i end - # Returns the monthly vote count of the bot + # The bot's monthly votes # @return [Integer] def monthlyPoints @obj["monthlyPoints"].to_i end - # Returns the total points of the bot + # The bot's total votes # @return [Integer] def points @obj["points"].to_i end - # Returns the Top.gg vanity URL code, can be nil + # The bot's vanity code, can be nil # @return [String] def vanity @obj["vanity"] end - # Returns the owner ids + # The bot's owner IDs # @return [Array] def owners @obj["owners"] end - # Return the bot tags + # The bot's tags # @return [Array] def tags @obj["tags"] end - # Returns an object containing the bot's review information. + # The bot's reviews # @return [Object] def reviews @obj["reviews"] diff --git a/lib/topgg/botSearch.rb b/lib/topgg/botSearch.rb index 31b99b3..0392d54 100644 --- a/lib/topgg/botSearch.rb +++ b/lib/topgg/botSearch.rb @@ -8,7 +8,7 @@ def initialize(obj) @obj = obj end - # Get raw hash response + # The raw hash of the parsed JSON object # @return [Hash] attr_reader :obj @@ -51,13 +51,13 @@ def offset end end - # Returns the results array + # The results array # @return [Array] def results @obj["results"].map { |b| Bot.new(b) } end - # Length of the results. + # The length of the results # @return [Integer] def size @obj["results"].length diff --git a/lib/topgg/stats.rb b/lib/topgg/stats.rb index 4bfba05..418da20 100644 --- a/lib/topgg/stats.rb +++ b/lib/topgg/stats.rb @@ -7,7 +7,8 @@ def initialize(obj) @obj = obj end - # Returns raw Hash of the response + # The raw hash of the parsed JSON object + # @return [Hash] attr_reader :obj alias raw obj diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index 0e6338d..e5af0bd 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -8,7 +8,7 @@ def initialize(obj) @obj = obj end - # Get raw hash response + # The raw hash of the parsed JSON object # @return [Hash] attr_reader :obj @@ -20,23 +20,23 @@ def error @obj["error"] end - # The Id of the user + # The user's ID def id @obj["id"] end - # The username of the user + # The user's username def username @obj["username"] end - # The avatar of the user + # The user's avatar URL # @return [String] def avatar @obj["avatar"] end - # The default avatar of the user + # The user's default avatar # @return [String] def defAvatar "" diff --git a/lib/topgg/vote.rb b/lib/topgg/vote.rb index 7b630d3..b58de3b 100644 --- a/lib/topgg/vote.rb +++ b/lib/topgg/vote.rb @@ -5,38 +5,38 @@ def initialize(obj) @obj = obj end - # Returns raw hash of the parsed json object + # The raw hash of the parsed JSON object # @return [Hash] attr_reader :obj alias raw obj alias data obj - # Returns the ID of the project that received a vote. + # The ID of the project that received a vote. # @return [String] def receiver_id !@obj["bot"].nil? ? @obj["guild"] : @obj["bot"] end - # Returns the ID of the Top.gg user who voted. + # The ID of the Top.gg user who voted. # @return [String] def voter_id @obj["user"] end - # Returns whether this vote is just a test done from the page settings. + # Whether this vote is just a test done from the page settings. # @return [Boolean] def is_test @obj["type"] == "test" end - # Returns whether the weekend multiplier is active, where a single vote counts as two. + # Whether the weekend multiplier is active, where a single vote counts as two. # @return [Boolean] def is_weekend @obj["isWeekend"] == true end - # Returns query strings found on the vote page. + # The query strings found on the vote page. # @return [Hash] def query return nil if @obj["query"].nil? diff --git a/lib/topgg/votes.rb b/lib/topgg/votes.rb index 59d2f0c..3e04f15 100644 --- a/lib/topgg/votes.rb +++ b/lib/topgg/votes.rb @@ -7,7 +7,7 @@ def initialize(obj) @obj = obj end - # Get raw hash return of the object + # The raw hash of the parsed JSON object # @return [Hash] attr_reader :obj @@ -24,7 +24,7 @@ def first end end - # Returns the results array + # The results array # @return [Array] def results @obj.map { |u| User.new(u) } diff --git a/topgg.gemspec b/topgg.gemspec index 8fe4670..e35fd59 100644 --- a/topgg.gemspec +++ b/topgg.gemspec @@ -6,8 +6,8 @@ Gem::Specification.new do |spec| spec.authors = ["Adonis Tremblay"] spec.email = ["rhydderchc@gmail.com"] - spec.summary = "A top.gg api wrapper for ruby." - spec.description = "This is a ruby library of the top.gg API." + spec.summary = "A Top.gg API wrapper for ruby." + spec.description = "This is a ruby library of the Top.gg API." spec.homepage = "https://github.com/Top-gg-Community/ruby-sdk" spec.license = "MIT" spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") From 98661bd723d59ca569c8c64b12362b8a85e7587b Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:17:01 +0700 Subject: [PATCH 17/27] revert: revert README.md for now (for diff readability) --- README.md | 183 ++++++++++-------------------------------------------- 1 file changed, 32 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index 2997976..26f3cce 100644 --- a/README.md +++ b/README.md @@ -1,176 +1,57 @@ -# Top.gg Ruby SDK - -The community-maintained Ruby library for Top.gg. - -## Chapters - -- [Installation](#installation) -- [Setting up](#setting-up) -- [Usage](#usage) - - [Getting a bot](#getting-a-bot) - - [Getting several bots](#getting-several-bots) - - [Getting your bot's voters](#getting-your-bots-voters) - - [Check if a user has voted for your bot](#check-if-a-user-has-voted-for-your-bot) - - [Getting your bot's server count](#getting-your-bots-server-count) - - [Posting your bot's server count](#posting-your-bots-server-count) - - [Automatically posting your bot's server count every few minutes](#automatically-posting-your-bots-server-count-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 bot](#being-notified-whenever-someone-voted-for-your-bot) +# [Top.gg](https://top.gg) Ruby -## Installation - -```sh -$ gem install topgg -``` - -## Setting up - -```rb -require "topgg" - -client = Topgg.new(ENV["TOPGG_TOKEN"]) -``` +The Top.gg Ruby SDK is a lighweight package, that allows you +to fetch data from the top.gg api and post data such as statistics to the website. -## Usage +It provides you with numerous methods to interact with the API. +## Dependencies -### Getting a bot +* Ruby -```rb -bot = client.get_bot("264811613708746752") -``` - -### Getting several bots - -```rb -bots = client.get_bots({ sort: "date", limit: 50, offset: 0 }) - -for bot in bots.results do - puts bot.username -end -``` - -### Getting your bot's voters +## Installation -#### First page +``` bash -```rb -voters = client.get_voters +gem install topgg -for voter in voters.results do - puts voter.username -end ``` +## Note -#### Subsequent pages - -```rb -voters = client.get_voters(2) - -for voter in voters.results do - puts voter.username -end -``` +You require a Token to interact with the Api. +The token can be found at `https://top.gg/bot/[YOUR_BOT_ID]/webhooks` -### Check if a user has voted for your bot +## Example -```rb -has_voted = client.voted?("661200758510977084") -``` +Here's a straightforward example of how to request data with the wrapper. -### Getting your bot's server count +```ruby +require 'topgg' -```rb -server_count = client.get_server_count -``` +client = Topgg.new("AUTH_TOKEN", "BOTID") -### Posting your bot's server count +client.get_bot("1234").defAvatar +# returns +# "6debd47ed13483642cf09e832ed0bc1b" -```rb -client.post_server_count(bot.server_count) ``` +### Auto Posting -### Automatically posting your bot's server count every few minutes +The library provides you with autoposting functionality, and autoposts at an interval of 30 minutes. +Here's how you can use it -For Discordrb: +```ruby +require 'topgg' +require 'discordrb' -```rb -require "discordrb" +bot = Discordrb::Bot.new token: "TOKEN" -bot = Discordrb::Bot.new(token: env["BOT_TOKEN"], intents: [:servers]) - -bot.ready do |event| - client.auto_post_stats(bot) - - puts "Bot is now ready!" +client = Topgg.new("AUTH_TOKEN", "BOTID") + bot.ready do |event| + client.auto_post_stats(bot) # The discordrb bot client. end - bot.run ``` -### Checking if the weekend vote multiplier is active +# Documentation -```rb -is_weekend = client.is_weekend? -``` - -### Generating widget URLs - -#### Large - -```rb -widget_url = Dbl::Widget.large(:discord_bot, "574652751745777665") -``` - -#### Votes - -```rb -widget_url = Dbl::Widget.votes(:discord_bot, "574652751745777665") -``` - -#### Owner - -```rb -widget_url = Dbl::Widget.owner(:discord_bot, "574652751745777665") -``` - -#### Social - -```rb -widget_url = Dbl::Widget.social(:discord_bot, "574652751745777665") -``` - -### Webhooks - -#### Being notified whenever someone voted for your bot - -##### Ruby on Rails - -In your `config/application.rb`: - -```rb -module MyServer - class Application < Rails::Application - # ... - - config.middleware.use Dbl::Webhook, - type: Dbl::Webhook::VOTE, - path: "/votes", - auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| - Rails.logger.info "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" - end - end -end -``` - -##### Sinatra - -```rb -use Dbl::Webhook, -type: Dbl::Webhook::VOTE, -path: "/votes", -auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| - puts "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" -end -``` \ No newline at end of file +Check out the api reference [here](https://rubydoc.info/gems/topgg/) From da1dbbfe09d4a65983bdf6368872af70ba59a143 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:19:07 +0700 Subject: [PATCH 18/27] revert: revert removal of discriminator --- lib/topgg/bot.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index d089fb1..f923393 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -88,6 +88,12 @@ def id @obj["id"] end + # The bot's discriminator + # @return [String] + def discriminator + "0" + end + # The bot's username # @return [String] def username From d3b1dbadab2008bbba39e9c5fc4c9d8fb3c2c86c Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:20:12 +0700 Subject: [PATCH 19/27] revert: shift defAvatar declaration order for diff readability --- lib/topgg/bot.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index f923393..5235aae 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -16,18 +16,18 @@ def initialize(obj) alias raw obj alias data obj - # The bot's default avatar - # @return [String] - def defAvatar - "" - end - # The error message if there's an error, otherwise nil # @return [String] def error @obj["error"] end + # The bot's default avatar + # @return [String] + def defAvatar + "" + end + # The bot's invite URL # @return [String] def invite From 19683896f9e642a09efb09bdf2bf3426cd59a65d Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:23:51 +0700 Subject: [PATCH 20/27] revert: revert the removal of shard_count, guilds, and shards --- lib/topgg/bot.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 5235aae..4047ec4 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -112,6 +112,24 @@ def server_count @obj["server_count"].to_i end + # The bot's posted shard count + # @return [Integer] + def shard_count + 0 + end + + # The configured servers in which the bot is in + # @return [Array] + def guilds + nil + end + + # The server count for each shard of the bot + # @return [Array] + def shards + nil + end + # The bot's monthly votes # @return [Integer] def monthlyPoints From a7cd27c4537b37f73ff9449753a1a5ed7ff97952 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:25:48 +0700 Subject: [PATCH 21/27] revert: revert the removal of lib --- lib/topgg/bot.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 4047ec4..3768b63 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -70,6 +70,12 @@ def prefix @obj["prefix"] end + # The bot's Discord library + # @return [String] + def lib + "" + end + # The bot's client ID # @return [String] def clientid From 2b1abb5ce0b3fa343bcb94fb1830c942a01d0cbb Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:27:00 +0700 Subject: [PATCH 22/27] revert: revert the removal of certifiedBot --- lib/topgg/bot.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 3768b63..09be749 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -148,6 +148,12 @@ def points @obj["points"].to_i end + # Whether the bot is certified + # @return [Boolean] + def certifiedBot + false + end + # The bot's vanity code, can be nil # @return [String] def vanity From 3b4eb2d74c7e67978c46d90403fbda7c4de4bea8 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:28:36 +0700 Subject: [PATCH 23/27] revert: revert the removal of bannerUrl and donatebotguildid --- lib/topgg/bot.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/topgg/bot.rb b/lib/topgg/bot.rb index 09be749..cb1ff18 100644 --- a/lib/topgg/bot.rb +++ b/lib/topgg/bot.rb @@ -172,6 +172,18 @@ def tags @obj["tags"] end + # The bot's banner URL + # @return [String] + def bannerUrl + "" + end + + # The bot's donatebot server ID + # @return [String] + def donatebotguildid + "" + end + # The bot's reviews # @return [Object] def reviews From 7672917bb8f4ccc2e99051f4956ac312e30ec842 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:30:30 +0700 Subject: [PATCH 24/27] fix: move declarations to help for diff readability and fix syntax error --- lib/topgg/botSearch.rb | 12 ++++++------ lib/topgg/user.rb | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/topgg/botSearch.rb b/lib/topgg/botSearch.rb index 0392d54..3526dd9 100644 --- a/lib/topgg/botSearch.rb +++ b/lib/topgg/botSearch.rb @@ -39,6 +39,12 @@ def count @obj["count"].to_i end + # The results array + # @return [Array] + def results + @obj["results"].map { |b| Bot.new(b) } + end + # The number of bots skipped, can be nil # @return [Integer] def offset @@ -51,12 +57,6 @@ def offset end end - # The results array - # @return [Array] - def results - @obj["results"].map { |b| Bot.new(b) } - end - # The length of the results # @return [Integer] def size diff --git a/lib/topgg/user.rb b/lib/topgg/user.rb index e5af0bd..35a69fa 100644 --- a/lib/topgg/user.rb +++ b/lib/topgg/user.rb @@ -76,5 +76,6 @@ def admin # @return [Boolean] def webMod false + end end end From 8a2035b4c9c4cf74f45fdeb4c5dc048efb374ff3 Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 11:35:43 +0700 Subject: [PATCH 25/27] fix: fix potential bug --- lib/lib.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/lib.rb b/lib/lib.rb index a71b85e..064abc8 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -5,6 +5,7 @@ require_relative "topgg/bot" require_relative "topgg/botSearch" +require_relative "topgg/stats" require_relative "topgg/user" require_relative "topgg/vote" require_relative "topgg/votes" @@ -84,7 +85,8 @@ def is_weekend? # @param page [Integer] The page to use. Defaults to 1. # @return [Dbl::Votes] def votes(page = 1) - page = 1 if page.to_i < 1 + page = page.to_i + page = 1 if page < 1 resp = @request.get("bots/#{@id}/votes", { page: page }) Dbl::Votes.new(resp) From a3a80a26e3f3fba2ee074b48a3c1f7a75333261a Mon Sep 17 00:00:00 2001 From: null8626 Date: Fri, 10 Oct 2025 13:32:40 +0700 Subject: [PATCH 26/27] [feat,doc]: add error handling and documentation tweaks --- README.md | 227 +++++++++++++++++++++++++++++++------ lib/lib.rb | 45 ++++++-- lib/topgg/utils/request.rb | 2 + lib/topgg/vote.rb | 40 +++---- lib/topgg/voteEvent.rb | 47 ++++++++ lib/topgg/webhooks.rb | 4 +- 6 files changed, 292 insertions(+), 73 deletions(-) create mode 100644 lib/topgg/voteEvent.rb diff --git a/README.md b/README.md index 26f3cce..4a5e4e8 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,220 @@ -# [Top.gg](https://top.gg) Ruby +# Top.gg Ruby SDK + +The community-maintained Ruby 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) -The Top.gg Ruby SDK is a lighweight package, that allows you -to fetch data from the top.gg api and post data such as statistics to the website. +## Installation -It provides you with numerous methods to interact with the API. -## Dependencies +```sh +$ gem install topgg +``` -* Ruby +## Setting up -## Installation +### API v1 + +> **NOTE**: API v1 also includes API v0. + +```rb +require "topgg" + +client = V1Topgg.new(ENV["TOPGG_TOKEN"]) +``` + +### API v0 + +```rb +require "topgg" -``` bash +client = Topgg.new(ENV["TOPGG_TOKEN"]) +``` + +## Usage + +### API v1 -gem install topgg +#### Getting your project's vote information of a user +```rb +vote = client.vote("661200758510977084") ``` -## Note -You require a Token to interact with the Api. -The token can be found at `https://top.gg/bot/[YOUR_BOT_ID]/webhooks` +#### Posting your bot's application commands list -## Example +##### Discordrb -Here's a straightforward example of how to request data with the wrapper. +```rb +commands = bot.rest.api.get_global_application_commands(bot.application_id).to_json -```ruby -require 'topgg' +client.post_commands(commands) +``` -client = Topgg.new("AUTH_TOKEN", "BOTID") +##### Raw -client.get_bot("1234").defAvatar -# returns -# "6debd47ed13483642cf09e832ed0bc1b" +```rb +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}]" +client.post_commands(commands) ``` -### Auto Posting -The library provides you with autoposting functionality, and autoposts at an interval of 30 minutes. -Here's how you can use it +### API v0 -```ruby -require 'topgg' -require 'discordrb' +#### Getting a bot -bot = Discordrb::Bot.new token: "TOKEN" +```rb +bot = client.get_bot("264811613708746752") +``` -client = Topgg.new("AUTH_TOKEN", "BOTID") - bot.ready do |event| - client.auto_post_stats(bot) # The discordrb bot client. +#### Getting several bots + +```rb +bots = client.search_bot({ sort: "id", limit: 50, offset: 0 }) + +for bot in bots.results do + puts bot.username end +``` + +#### Getting your project's voters + +##### First page + +```rb +voters = client.votes + +for voter in voters.results do + puts voter.username +end +``` + +##### Subsequent pages + +```rb +voters = client.votes(2) + +for voter in voters.results do + puts voter.username +end +``` + +#### Check if a user has voted for your project + +```rb +has_voted = client.voted?("8226924471638491136") +``` + +#### Getting your bot's statistics + +```rb +stats = client.get_stats +``` + +#### Posting your bot's statistics + +```rb +client.post_stats(bot.server_count) +``` + +#### Automatically posting your bot's statistics every few minutes + +With Discordrb: + +```rb +require "discordrb" + +bot = Discordrb::Bot.new(token: env["BOT_TOKEN"], intents: [:servers]) + +bot.ready do |event| + client.auto_post_stats(bot) + + puts("Bot is now ready!") +end + bot.run ``` -# Documentation +#### Checking if the weekend vote multiplier is active + +```rb +is_weekend = client.is_weekend? +``` + +#### Generating widget URLs + +##### Large + +```rb +widget_url = Dbl::Widget.large(:discord_bot, "574652751745777665") +``` + +##### Votes + +```rb +widget_url = Dbl::Widget.votes(:discord_bot, "574652751745777665") +``` + +##### Owner + +```rb +widget_url = Dbl::Widget.owner(:discord_bot, "574652751745777665") +``` + +##### Social + +```rb +widget_url = Dbl::Widget.social(:discord_bot, "574652751745777665") +``` + +### Webhooks + +#### Being notified whenever someone voted for your project -Check out the api reference [here](https://rubydoc.info/gems/topgg/) +##### Ruby on Rails + +In your `config/application.rb`: + +```rb +module MyServer + class Application < Rails::Application + # ... + + config.middleware.use Dbl::Webhook, + type: Dbl::Webhook::VOTE, + path: "/votes", + auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| + Rails.logger.info "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" + end + end +end +``` + +##### Sinatra + +```rb +use Dbl::Webhook, +type: Dbl::Webhook::VOTE, +path: "/votes", +auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| + puts "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" +end +``` \ No newline at end of file diff --git a/lib/lib.rb b/lib/lib.rb index 064abc8..f98778c 100644 --- a/lib/lib.rb +++ b/lib/lib.rb @@ -14,10 +14,10 @@ require_relative "topgg/utils/request" # Class Topgg -# The class instantiates all the methods for API requests and posts. +# Top.gg API v0 client class Topgg - # initializes the class attributes. - # @param token [String] The authorization token from top.gg + # Initializes the client + # @param token [String] Your Top.gg API token def initialize(token) begin token_section = token.split('.')[1] @@ -35,14 +35,14 @@ def initialize(token) @request = Dbl::Utils::Request.new(token) end - # Fetches bot statistics from top.gg + # Get Discord bot statistics from top.gg # @param id [String] The bot's ID # @return [Dbl::Bot] The Bot Object def get_bot(id) Dbl::Bot.new(@request.get("bots/#{id}")) end - # Searches bots from Top.gg using a keyword query. + # Searches Discord bots from Top.gg using a keyword query. # @param [Object] params The parameters that can be used to query a search # To know what the parameters are check it out here # @return [Dbl::BotSearch] The BotSearch Object @@ -61,9 +61,7 @@ def user(id) # @param id [String] The bot's ID. Unused, no longer has an effect. # @return [Dbl::Stats] def get_stats(id = nil) - resp = @request.get("bots/stats") - - Dbl::Stats.new(resp) + Dbl::Stats.new(@request.get("bots/stats")) end # Mini-method to query if your project was voted by the user in the past 12 hours. @@ -87,12 +85,11 @@ def is_weekend? def votes(page = 1) page = page.to_i page = 1 if page < 1 - resp = @request.get("bots/#{@id}/votes", { page: page }) - Dbl::Votes.new(resp) + Dbl::Votes.new(@request.get("bots/#{@id}/votes", { page: page })) end - # Posts your Discord bot's server count to the API. This will update the server count in your 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 server_count [Integer] The amount of servers the bot is in. Must not be less than 1. # @param shards [Integer] The amount of servers the bot is in per shard. Unused, no longer has an effect. # @param shard_count [Integer] The total number of shards. Unused, no longer has an effect. @@ -106,7 +103,7 @@ def post_stats(server_count, shards = nil, shard_count = nil) ) end - # Auto-posts stats to the Top.gg website + # Auto-posts your Discord bot's stats to the Top.gg website # @param client [Discordrb::Bot] instanceof discordrb client. def auto_post_stats(client) semaphore = Mutex.new @@ -136,3 +133,27 @@ def interval(seconds) end end end + +# Top.gg API v1 client +class V1Topgg < Topgg + # Updates the application commands list in your Discord bot's Top.gg page. + # @param commands [String] A list of application commands in raw Discord API JSON objects. This cannot be empty. + def post_commands(commands) + @request.post("v1/projects/@me/commands", commands) + end + + # Get the latest vote information of a Top.gg user on your project. + # @param id [String] The user's ID. + # @param source [String] The ID type to use. Defaults to "discord". + # @return [Dbl::Vote] + def vote(id, source = "discord") + raise ArgumentError, "source must be either \"discord\" or \"topgg\"" unless source == "discord" or source == "topgg" + + begin + Dbl::Vote.new(@request.get("v1/projects/@me/votes/#{id}", { source: source })) + rescue Net::HTTPError => err + return nil if err.response.code == "404" + raise + end + end +end \ No newline at end of file diff --git a/lib/topgg/utils/request.rb b/lib/topgg/utils/request.rb index 4add0f4..7da131a 100644 --- a/lib/topgg/utils/request.rb +++ b/lib/topgg/utils/request.rb @@ -24,6 +24,8 @@ def get(params, query=nil) request.add_field "Authorization", "Bearer #{@token}" response = http.request(request) + raise Net::HTTPError.new("Top.gg HTTP error: #{response.code}", response) unless response.code.start_with?('2') + JSON.parse(response.body) end diff --git a/lib/topgg/vote.rb b/lib/topgg/vote.rb index b58de3b..a6546b9 100644 --- a/lib/topgg/vote.rb +++ b/lib/topgg/vote.rb @@ -1,5 +1,5 @@ module Dbl - # A dispatched Top.gg vote event + # A Top.gg vote information class Vote def initialize(obj) @obj = obj @@ -12,36 +12,22 @@ def initialize(obj) alias raw obj alias data obj - # The ID of the project that received a vote. - # @return [String] - def receiver_id - !@obj["bot"].nil? ? @obj["guild"] : @obj["bot"] + # When the vote was cast + # @return [Date] + def voted_at + Date.parse(@obj["created_at"]) end - # The ID of the Top.gg user who voted. - # @return [String] - def voter_id - @obj["user"] + # When the vote expires + # @return [Date] + def expires_at + Date.parse(@obj["expires_at"]) end - # Whether this vote is just a test done from the page settings. - # @return [Boolean] - def is_test - @obj["type"] == "test" - end - - # Whether the weekend multiplier is active, where a single vote counts as two. - # @return [Boolean] - def is_weekend - @obj["isWeekend"] == true - end - - # The query strings found on the vote page. - # @return [Hash] - def query - return nil if @obj["query"].nil? - - CGI.parse(@obj["query"]).transform_values(&:first) + # The vote's weight + # @return [Integer] + def weight + @obj["weight"] end end end \ No newline at end of file diff --git a/lib/topgg/voteEvent.rb b/lib/topgg/voteEvent.rb new file mode 100644 index 0000000..e6b23e3 --- /dev/null +++ b/lib/topgg/voteEvent.rb @@ -0,0 +1,47 @@ +module Dbl + # A dispatched Top.gg vote event + class VoteEvent + def initialize(obj) + @obj = obj + end + + # The raw hash of the parsed JSON object + # @return [Hash] + attr_reader :obj + + alias raw obj + alias data obj + + # The ID of the project that received a vote. + # @return [String] + def receiver_id + !@obj["bot"].nil? ? @obj["guild"] : @obj["bot"] + end + + # The ID of the Top.gg user who voted. + # @return [String] + def voter_id + @obj["user"] + end + + # Whether this vote is just a test done from the page settings. + # @return [Boolean] + def is_test + @obj["type"] == "test" + end + + # Whether the weekend multiplier is active, where a single vote counts as two. + # @return [Boolean] + def is_weekend + @obj["isWeekend"] == true + end + + # The query strings found on the vote page. + # @return [Hash] + def query + return nil if @obj["query"].nil? + + CGI.parse(@obj["query"]).transform_values(&:first) + end + end +end \ No newline at end of file diff --git a/lib/topgg/webhooks.rb b/lib/topgg/webhooks.rb index 4ec9f47..09b5963 100644 --- a/lib/topgg/webhooks.rb +++ b/lib/topgg/webhooks.rb @@ -1,12 +1,12 @@ require "rack" require "cgi" -require_relative "vote" +require_relative "voteEvent" module Dbl # A wrapper for directly receiving events from Top.gg's servers class Webhook - VOTE = ->(json) { Vote.new(json) } + VOTE = ->(json) { VoteEvent.new(json) } def initialize(app, type:, path:, auth:, &callback) raise ArgumentError, "A callback must be provided" unless callback From 2b8c8050a89ca7561e85c5cdbc00cf347ea7a585 Mon Sep 17 00:00:00 2001 From: null <60427892+null8626@users.noreply.github.com> Date: Tue, 21 Oct 2025 00:08:22 +0700 Subject: [PATCH 27/27] 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 4a5e4e8..411ebcf 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ The community-maintained Ruby 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) @@ -217,4 +217,4 @@ path: "/votes", auth: ENV["MY_TOPGG_WEBHOOK_SECRET"] do |vote| puts "A user with the ID of #{vote.voter_id} has voted us on Top.gg!" end -``` \ No newline at end of file +```