README.md

# TopggEx

[![Hex.pm](https://img.shields.io/hexpm/v/topgg_ex.svg)](https://hex.pm/packages/topgg_ex)
[![Documentation](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/topgg_ex/)
[![License](https://img.shields.io/hexpm/l/topgg_ex.svg)](https://github.com/jilv220/topgg_ex/blob/main/LICENSE)

A community Elixir SDK for the [Top.gg](https://top.gg) API, allowing you to interact with Discord bot statistics, user votes, and bot information.

## Features

- ๐Ÿš€ **Complete API Coverage**: All Top.gg API endpoints supported
- ๐Ÿ”’ **Type Safety**: Full typespecs and structured data
- โšก **HTTP/2 Support**: Built on Finch for modern HTTP performance
- ๐Ÿงช **Well Tested**: Comprehensive test suite with 95%+ coverage
- ๐Ÿ“š **Excellent Documentation**: Detailed docs with examples
- ๐Ÿ—๏ธ **Clean Architecture**: Separated HTTP client for maintainability

## Installation

Add `topgg_ex` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:topgg_ex, "~> 0.1.0"},
    {:finch, "~> 0.19"}  # Required HTTP client
  ]
end
```

Then run:

```bash
mix deps.get
```

## Quick Start

### 1. Setup

First, add Finch to your application's supervision tree:

```elixir
# In your application.ex
children = [
  {Finch, name: :topgg_finch}
]
```

### 2. Create API Client

```elixir
# Get your token from https://top.gg/api/docs#mybots
{:ok, api} = TopggEx.Api.new("your_topgg_token_here")
```

### 3. Post Bot Statistics

```elixir
# Update your bot's server count
{:ok, stats} = TopggEx.Api.post_stats(api, %{server_count: 1250})
```

## Usage Examples

### Bot Statistics

```elixir
# Post bot stats
{:ok, _} = TopggEx.Api.post_stats(api, %{
  server_count: 1250,
  shard_count: 2,
  shards: [625, 625]
})

# Get your bot's current stats
{:ok, stats} = TopggEx.Api.get_stats(api)
# => %{server_count: 1250, shard_count: 2, shards: [625, 625]}
```

### Bot Information

```elixir
# Get information about any bot
{:ok, bot} = TopggEx.Api.get_bot(api, "461521980492087297")
# => %{"id" => "461521980492087297", "username" => "Shiro", ...}

# Search for bots
{:ok, results} = TopggEx.Api.get_bots(api, %{
  search: %{username: "music"},
  limit: 10,
  fields: ["id", "username", "short_description"]
})
```

### Vote Checking

```elixir
# Check if a user has voted
{:ok, has_voted?} = TopggEx.Api.has_voted(api, "205680187394752512")
# => true or false

# Get recent voters
{:ok, voters} = TopggEx.Api.get_votes(api)
# => [%{"username" => "Example", "id" => "123...", "avatar" => "https://..."}, ...]

# Check weekend multiplier status
{:ok, is_weekend?} = TopggEx.Api.is_weekend(api)
# => true or false
```

### Advanced Usage

```elixir
# Custom Finch instance
{:ok, api} = TopggEx.Api.new("your_token", %{
  finch_name: :my_custom_finch,
  base_url: "https://top.gg/api"  # Optional custom base URL
})

# Complex bot search
{:ok, results} = TopggEx.Api.get_bots(api, %{
  search: %{
    username: "music bot",
    tags: "music"
  },
  sort: "server_count",
  limit: 50,
  fields: ["id", "username", "short_description", "server_count"]
})
```

## API Reference

### Core Functions

| Function       | Description              | Parameters         |
| -------------- | ------------------------ | ------------------ |
| `new/2`        | Create API client        | `token`, `options` |
| `post_stats/2` | Update bot statistics    | `api`, `stats`     |
| `get_stats/1`  | Get bot statistics       | `api`              |
| `get_bot/2`    | Get bot information      | `api`, `bot_id`    |
| `get_bots/2`   | Search bots              | `api`, `query`     |
| `get_votes/2`  | Get recent voters        | `api`, `page`      |
| `has_voted/2`  | Check user vote status   | `api`, `user_id`   |
| `is_weekend/1` | Check weekend multiplier | `api`              |

### Error Handling

All functions return `{:ok, result}` on success or `{:error, reason}` on failure:

```elixir
case TopggEx.Api.post_stats(api, %{server_count: 100}) do
  {:ok, stats} ->
    IO.puts("Stats updated successfully!")
  {:error, %{status: 401}} ->
    IO.puts("Invalid API token")
  {:error, %{status: 429}} ->
    IO.puts("Rate limited - try again later")
  {:error, reason} ->
    IO.puts("Network error: #{inspect(reason)}")
end
```

## Configuration

### Environment Variables

You can set your Top.gg token via environment variables:

```elixir
# config/runtime.exs
config :my_app, :topgg_token, System.get_env("TOPGG_TOKEN")

# In your application
token = Application.get_env(:my_app, :topgg_token)
{:ok, api} = TopggEx.Api.new(token)
```

### Custom HTTP Client Options

```elixir
{:ok, api} = TopggEx.Api.new("your_token", %{
  finch_name: :my_finch,      # Custom Finch instance name
  base_url: "https://top.gg/api"  # Custom API base URL
})
```

## Rate Limiting

Top.gg API has rate limits. The library will return appropriate errors:

- **429 Too Many Requests**: You've hit the rate limit
- **403 Forbidden**: Invalid token or insufficient permissions

Implement exponential backoff for production applications:

```elixir
defmodule MyBot.Stats do
  def update_stats_with_retry(api, stats, retries \\ 3) do
    case TopggEx.Api.post_stats(api, stats) do
      {:ok, result} -> {:ok, result}
      {:error, %{status: 429}} when retries > 0 ->
        Process.sleep(1000 * (4 - retries))  # Exponential backoff
        update_stats_with_retry(api, stats, retries - 1)
      error -> error
    end
  end
end
```

## Testing

The library includes comprehensive tests. Run them with:

```bash
mix test
```

For testing your own applications, you can mock the HTTP client:

```elixir
# In your tests
setup do
  bypass = Bypass.open()

  {:ok, api} = TopggEx.Api.new("test_token", %{
    base_url: "http://localhost:#{bypass.port}/api"
  })

  {:ok, %{bypass: bypass, api: api}}
end
```

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request

### Development

```bash
# Get dependencies
mix deps.get

# Run tests
mix test

# Generate documentation
mix docs

# Check formatting
mix format --check-formatted

# Run static analysis
mix dialyzer
```

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Links

- [Top.gg API Documentation](https://docs.top.gg)
- [Hex Package](https://hex.pm/packages/topgg_ex)
- [Documentation](https://hexdocs.pm/topgg_ex/)
- [GitHub Repository](https://github.com/jilv220/topgg_ex)

## Acknowledgments

- Thanks to the [Top.gg](https://top.gg) team for providing the API
- Built with [Finch](https://github.com/sneako/finch) for modern HTTP performance
- Inspired by the JavaScript [topgg.js](https://github.com/top-gg/node-sdk) library