Class: TopTL::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/toptl/client.rb

Overview

Synchronous client for the TOP.TL public API.

client = TopTL::Client.new("toptl_xxx")
listing = client.get_listing("mybot")
puts listing.title, listing.vote_count

Constant Summary collapse

DEFAULT_BASE_URL =
"https://top.tl/api"
DEFAULT_TIMEOUT =
15

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, user_agent: nil) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    API key from top.tl/profile → API Keys

  • base_url (String) (defaults to: DEFAULT_BASE_URL)

    override for self-hosted / staging environments

  • timeout (Integer, Float) (defaults to: DEFAULT_TIMEOUT)

    seconds before any HTTP request is abandoned

  • user_agent (String, nil) (defaults to: nil)

    extra UA suffix appended to the SDK’s UA

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
# File 'lib/toptl/client.rb', line 21

def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, user_agent: nil)
  raise ArgumentError, "api_key is required" if api_key.nil? || api_key.to_s.empty?

  @api_key = api_key
  @base_url = base_url.to_s.chomp("/")
  @timeout = timeout
  base_ua = "toptl-ruby/#{TopTL::VERSION}"
  @user_agent = user_agent ? "#{base_ua} #{user_agent}" : base_ua
end

Instance Method Details

#batch_post_stats(items) ⇒ Array<StatsResult>

Post stats for up to 25 listings in a single request.

Parameters:

  • items (Array<Hash>)

    each item must include :username plus any of :member_count, :group_count, :channel_count, :bot_serves

Returns:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/toptl/client.rb', line 81

def batch_post_stats(items)
  return [] if items.nil? || items.empty?

  body = items.map do |i|
    h = i.transform_keys { |k| k.is_a?(String) ? k.to_sym : k }
    entry = { "username" => h[:username] }
    entry["memberCount"]  = h[:member_count]  if h.key?(:member_count)
    entry["groupCount"]   = h[:group_count]   if h.key?(:group_count)
    entry["channelCount"] = h[:channel_count] if h.key?(:channel_count)
    entry["botServes"]    = h[:bot_serves]    if h.key?(:bot_serves)
    entry
  end

  data = request(:post, "/v1/stats/batch", body: body)
  return [] unless data.is_a?(Array)

  data.map { |r| StatsResult.from_hash(r.is_a?(Hash) ? r : {}) }
end

#get_global_statsGlobalStats

Site-wide totals: ‘{ total, channels, groups, bots }`.

Returns:



118
119
120
121
# File 'lib/toptl/client.rb', line 118

def get_global_stats
  data = request(:get, "/v1/stats")
  GlobalStats.from_hash(data.is_a?(Hash) ? data : {})
end

#get_listing(username) ⇒ Listing

Fetch a listing by its Telegram username (without leading ‘@`).

Returns:



37
38
39
40
# File 'lib/toptl/client.rb', line 37

def get_listing(username)
  data = request(:get, "/v1/listing/#{username}")
  Listing.from_hash(data.is_a?(Hash) ? data : {})
end

#get_votes(username, limit: 20) ⇒ Array<Voter>

Recent voters for a listing (most recent first).

Returns:



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/toptl/client.rb', line 44

def get_votes(username, limit: 20)
  data = request(:get, "/v1/listing/#{username}/votes", params: { limit: limit })
  items = if data.is_a?(Array)
            data
          elsif data.is_a?(Hash)
            data["items"] || []
          else
            []
          end
  items.map { |v| Voter.from_hash(v) }
end

#has_voted(username, user_id) ⇒ VoteCheck

Has this Telegram user id voted for the given listing?

Returns:



58
59
60
61
# File 'lib/toptl/client.rb', line 58

def has_voted(username, user_id)
  data = request(:get, "/v1/listing/#{username}/has-voted/#{user_id}")
  VoteCheck.from_hash(data.is_a?(Hash) ? data : {})
end

#post_stats(username, member_count: nil, group_count: nil, channel_count: nil, bot_serves: nil) ⇒ StatsResult

Update counters on a listing you own. Only the keyword arguments you pass are sent; unspecified fields are left untouched on the server.

Returns:



67
68
69
70
71
72
73
74
75
# File 'lib/toptl/client.rb', line 67

def post_stats(username, member_count: nil, group_count: nil, channel_count: nil, bot_serves: nil)
  body = build_stats_body(member_count, group_count, channel_count, bot_serves)
  if body.empty?
    raise ArgumentError, "post_stats needs at least one of member_count, group_count, channel_count, or bot_serves"
  end

  data = request(:post, "/v1/listing/#{username}/stats", body: body)
  StatsResult.from_hash(data.is_a?(Hash) ? data : { "success" => true })
end

#set_webhook(username, url, reward_title: nil) ⇒ WebhookConfig

Register the URL TOP.TL should POST to when a user votes.

Returns:



102
103
104
105
106
107
# File 'lib/toptl/client.rb', line 102

def set_webhook(username, url, reward_title: nil)
  body = { "url" => url }
  body["rewardTitle"] = reward_title unless reward_title.nil?
  data = request(:put, "/v1/listing/#{username}/webhook", body: body)
  WebhookConfig.from_hash(data.is_a?(Hash) ? data : { "url" => url })
end

#test_webhook(username) ⇒ WebhookTestResult

Send a synthetic vote event to the listing’s configured webhook.

Returns:



111
112
113
114
# File 'lib/toptl/client.rb', line 111

def test_webhook(username)
  data = request(:post, "/v1/listing/#{username}/webhook/test")
  WebhookTestResult.from_hash(data.is_a?(Hash) ? data : { "success" => false })
end