{"id":45645876,"url":"https://github.com/tornium/tornex","last_synced_at":"2026-02-24T04:01:28.037Z","repository":{"id":256861713,"uuid":"819658431","full_name":"Tornium/Tornex","owner":"Tornium","description":"Robust API call planning and execution for Torn City in Elixir.","archived":false,"fork":false,"pushed_at":"2026-02-03T01:27:56.000Z","size":311,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-03T06:44:26.498Z","etag":null,"topics":["torn","torn-city","torn-city-api"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tornium.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-25T00:38:12.000Z","updated_at":"2026-01-30T19:42:19.000Z","dependencies_parsed_at":"2024-09-13T13:13:25.464Z","dependency_job_id":"49004f9a-49e9-49cb-986f-4fd3b313e09e","html_url":"https://github.com/Tornium/Tornex","commit_stats":null,"previous_names":["tornium/tornex"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/Tornium/Tornex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tornium%2FTornex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tornium%2FTornex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tornium%2FTornex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tornium%2FTornex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tornium","download_url":"https://codeload.github.com/Tornium/Tornex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tornium%2FTornex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29771038,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T04:01:02.180Z","status":"ssl_error","status_checked_at":"2026-02-24T03:59:49.901Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["torn","torn-city","torn-city-api"],"created_at":"2026-02-24T04:01:27.107Z","updated_at":"2026-02-24T04:01:28.032Z","avatar_url":"https://github.com/Tornium.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tornex\nAn Elixir library providing robust API call planning and execution for the [Torn City](https://torn.com) API.\n\n## Features\n- Efficient API ratelimiting and planning using buckets and prioritized requests\n- `:telemetry`-based logging (with included support for [PromEx](https://hex.pm/packages/prom_ex))\n- Support for APIv1 and APIv2\n- Support for multiple BEAM nodes\n- Support for multi-node clusters\n- Support for per-node API ratelimiting\n\n## Roadmap\n- [x] Per-node global ratelimit\n- [ ] Combine similar queries to reduce throughput\n- [x] Multi-node support\n- [ ] APIv2 struct coalescing using [torngen](https://github.com/Tornium/torngen)\n- [ ] APIv2 mocking server using [torngen](https://github.com/Tornium/torngen)\n\n## Installation\nOnce [available in Hex](https://hex.pm/docs/publish), the library can be installed\nby adding `tornex` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:tornex, \"~\u003e 0.4.0\"}\n  ]\nend\n```\n\nFor latest changes, you can also install the library directly from [GitHub](https://github.com/Tornium/tornex):\n\n```elixir\ndef deps do\n  [\n    {:tornex, github: \"Tornium/tornex\"}\n  ]\nend\n```\n\n## Usage\nAdd the supervisor `Tornex.Scheduler.Supervisor` and `Tornex.NodeRatelimiter` to your application supervisor. If you are using the default telemetry handler using `Tornex.Telemetry.attach_default_handler`, make sure to start the handler before starting the supervisor.\n\n\u003c!-- tabs-open --\u003e\n### APIv1\nCreate a `Tornex.Query` struct containing the request information:\n```elixir\nrequest = %Tornex.Query{\n    resource: \"user\",\n    resource_id: 2383326,\n    key: api_key,\n    selections: [\"attacks\", \"basic\"],\n    key_owner: 2383326,\n    nice: 10\n}\n```\n\nThe query struct must contain the following values:\n- `resource`: The name of the resource.\n- `resource_id`: The ID of the resource even if the request is against the key owner's user, faction, etc.\n- `key`: The API key to be used.\n- `key_owner`: Any other unique identifier (suggested to use Torn ID) of the API key owner.\n- `nice`: The priority of the request (following the Linux niceness values) where -20 is the highest priority and 19 is the lowest priority.\n\n### APIv2\nTo use the auto-generated client for APIv2, you will need to add the [Tornium/torngen_elixir_client](https://github.com/Tornium/torngen_elixir_client) library to your dependencies. Without installing this client, you will have to use the APIv1 style requests through `Tornex.Query` and prepend `v2` to the resource (e.g. `v2/user`).\n\nCreate a `Tornex.SpecQuery` struct containing the request information:\n```elixir\nrequest =\n    Tornex.SpecQuery.new()\n    |\u003e Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Attacks)\n    |\u003e Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Basic)\n    |\u003e Tornex.SpecQuery.put_key(api_key)\n```\n\u003c!-- tabs-close --\u003e\n\nOnce the query struct has been constructed, the request can be enqueued into the key owner's queue with `Tornex.Scheduler.Bucket.enqueue/1` to be made depending on the request's priority and the state of the key owner's queue. Alternatively, the request can be performed immediately with `Tornex.API.get/1` which performs no ratelimiting. However, both methods are blocking.\n\n```elixir\nresponse = Tornex.Scheduler.Bucket.enqueue(request)\n\ncase response do\n    {:error, :timeout} -\u003e\n        IO.puts(\"timeout\")\n\n    {:error, _} -\u003e\n        IO.puts(\"unknown\")\n\n    %{\"name\" =\u003e name, \"attacks\" =\u003e attacks} -\u003e\n        IO.puts(\"#{name} =\u003e #{Enum.count(attacks)} attacks\")\nend\n```\n\n## Documentation\nDocumentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) and can be found at \u003chttps://hexdocs.pm/tornex\u003e.\n\n## License\nCopyright 2024-2025 tiksan\n\nThis project is licensed under Apache 2.0; see [LICENSE.md](LICENSE.md) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftornium%2Ftornex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftornium%2Ftornex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftornium%2Ftornex/lists"}