0.0
No commit activity in last 3 years
No release in over 3 years
Ruby Poe Watch API wrapper.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 4.1.0
 Project Readme

Poe Watch Ruby API

A Ruby wrapper around the poe.watch API. It implements the same DSL you are used to when using ActiveRecord but doesn't require Rails at all.

Inspired by klayveR's poe-watch-api JS wrapper.

Table of content

  • Requirements
  • Installation
  • Dependencies
  • Usage
    • Items
      • Get all item data
      • Get multiple specific items
      • Find one specific item
      • Item properties
    • Item price data
      • Price data properties
    • Leagues
      • Get all league data
      • Get multiple specific leagues
      • Find one specific league
      • League properties
    • Categories
      • Get all categories data
      • Get multiple specific categories
      • Find one specific category
      • Category properties
    • API Cache
  • Shortcomings
  • Contribution
  • License

Requirements

  • Redis: 4.0+
  • Ruby 2.3+

Installation

gem install poe-watch-api

or add it to your Gemfile

gem 'poe-watch-api'

Then

require 'poe_watch'

Dependencies

This library has a dependency over redis. For it to work you need to have redis installed on your machine (and your server, in production, if using Heroku, you can use an addon like rediscloud). We use redis because we need to cache the data from Poe Watch to avoid refetching all the items data too often (there are almost 30k items in PoE which is quite a lot).

There are two ways of making this gem work with redis:

  • Set a global $redis variable. Example:
$redis = Redis.new

# In production for instance if you were to use rediscloud on heroku :
url = ENV["REDISCLOUD_URL"] # or whatever is the URL of your redis

if url
  $redis = Redis.new(:url => url)
end
  • Provide your own instance of redis through PoeWatch::Api.redis = Redis.new(YOUR_PARAMS) Example:
PoeWatch::Api.redis = Redis.new

# In production for instance, if you were to use rediscloud on heroku:
url = ENV["REDISCLOUD_URL"] # or whatever is the URL of your redis

if url
  PoeWatch::Api.redis = Redis.new(:url => url)
end

The total footprint of the data from PoeWatch API in redis is a bit less than 2 megabytes. You can check the exact memory footprint in your redis by calling PoeWatch::Api.memory_footprint, the data will be displayed in kilobytes. The default time to live (TTL) of the cache is 1 day.

Usage

Here is a simple usage example:

require 'poe_watch'

# See the dependencies section
PoeWatch::Api.redis = Redis.new

# Non mandatory
PoeWatch::Api.refresh!(3600) # cache for 1 hour

PoeWatch::Item.find({ name: "Circle of Nostalgia" }).price_for_league('Metamorph')

Items

Get all item data

PoeWatch::Item.all # => array of PoeWatch::Item objects
PoeWatch::Item.count  # => total number of items

Get multiple specific items

items = PoeWatch::Item.where(name: /circle/i) # Returns all items with a name containing "circle"

items.first.id # => 223
items.first.name # => "Hubris Circlet"

Find one specific item

item = PoeWatch::Item.find(name: "Circle of Nostalgia") # Returns the item "Circle of Nostalgia"
item = PoeWatch::Item.find(name: /circle/i) # Returns the first item with a name containing "circle"

item.id # => 223
item.name # => "Hubris Circlet"

Item properties

All properties have an accessor you can use, e.g: item.id, item.name, item.category. All boolean properties have an additionnal question mark accessor, e.g: item.gem_is_corrupted?.

Items only have relevant properties (e.g: map tiers only on maps, stack_size only on currencies, etc...)

Name Type Description
id Integer poe.watch ID
name String name
type String base type
category String item category
group String item category group
frame Integer frame type (item rarity)
map_series Integer 5 for Synthesis, 1 for Awakening, etc
map_tier Integer map tier
gem_level Integer gem level
gem_quality Integer gem quality
gem_is_corrupted Boolean is the gem corrupted
link_count Integer links count
base_item_level Integer item level
variation String variations of the same item (e.g: Vessel of Vinktar)
enchant_min Integer enchantment's minimum has numeric value
enchant_max Integer enchantment's maximum has numeric value
relic Integer whether the item is a relic or not. true always sets properties.frame to 9
icon String icon URL
influences Array shaper / elder / conqueror influences
stack_size Integer default stack size of item type

Item price data

item = PoeWatch::Item.find(name: "Circle of Nostalgia")

# Returns price data for all leagues
item.prices

# Returns price data for all leagues matching the name
item.price_for_leagues("Metamorph") # => all metamorph leagues (HC / SC) price data

# Returns price data for a specific league
item.price_for_leagues("Metamorph") # => Price data for "Metamorph"
item.price_for_leagues(/metamorph/i) # => Price data for the first metamorph league found

Price data properties

Name Type Description
id Integer league ID
name String league name
display String league display name
current Integer nb of items currently on sale
daily Integer nb of items found per 24h
accepted Integer nb of items accepted for price calculation
exalted Float mean price in exalted
max Float max accepted average price
min Float min accepted average price
mean Float mean average price
median Float median average price
mode Float mode average price
active Boolean is league still active
start String league end date
end String league end date

Leagues

Get all league data

PoeWatch::League.all # => array of PoeWatch::League objects
PoeWatch::League.count  # => total number of leagues

Get multiple specific leagues

leagues = PoeWatch::League.where(hardcore: false) # Returns all non hardcore leagues
leagues = PoeWatch::League.where(name: /metamorph/i) # You can use regular expressions or strings for your queries

leagues.first.name # => "Hardcore Metamorph"
leagues.first.hardcore? # => true
leagues.first.start? # => "2019-12-13T20:00:00Z"

Find one specific league

league = PoeWatch::League.find(name: "Metamorph") # Return the non hardcore "Metamorph" league
league = PoeWatch::League.find(name: /metamorph/i, hardcore: false) # Will return the first non hardcore Metamorph league found

league.name # => "Metamorph"
league.hardcore? # => false
league.start? # => "2019-12-13T20:00:00Z"

League properties

All properties have an accessor you can use, e.g: league.id, league.name, league.hardcore. All boolean properties have an additionnal question mark accessor, e.g: league.hardcore?.

Name Type Description
id Integer poe.watch ID
name String name
display String display name
hardcore Boolean is hardcore
active Boolean is active
start String start date
end String end date
challenge Boolean is a challenge league
event Boolean is an event league
upcoming Boolean is upcoming

Categories

Get all categories data

PoeWatch::Categories.all # => array of PoeWatch::Category objects
PoeWatch::Categories.count  # => total number of categories

Get multiple specific categories

categories = PoeWatch::Category.where(name: /accessory/i) # You can use regular expressions or strings for your queries

categories.first.display # => "Accessories"

Find one specific category

category = PoeWatch::Category.find(name: /accessory/i) # You can use regular expressions or strings for your queries

category.display # => "Accessories"
category.groups # => [#<OpenStruct id=1, name="amulet", display="Amulets">, ...]
category.groups.first.name # => "amulet"

Category properties

All properties have an accessor you can use, e.g: category.name, category.groups.

Name Type Description
id Integer poe.watch ID
name String name
display String display name
groups Array<OpenStruct> an array of item types that belongs to this category. Stored as OpenStructs so you can access them with the . syntax. A group has 3 attributes: id, name and display

API Cache

# Fetch all the data from poe.watch API and cache it for the next 1 day.
# You don't actually need to call this. It is automatically called when using `::find`, `::where`, `::all` or `::count`, and won't do anything if the cache already contains data. 
# Although beware that if you don't call it first, the first call to find/where/all/count every 1 day will take longer (around 2-4 seconds, there are quite a lot of items to fetch).
PoeWatch::Api.refresh! 
# You can also specify a cache TTL different than 1 day
PoeWatch::Api.refresh!(3600) # 1 hour cache

# If you need to force clear the cache, you can use 
PoeWatch::Api.clear!

# You can check if the cache has expired with 
PoeWatch::Api.has_expired?
# Or do the opposite with 
PoeWatch::Api.ready?

Shortcomings

  • When you want to fetch the price of an item, we do a request each time using the PoE API /item endpoint, which is not ideal. Ideally we'd want to use the /compact API for that but I haven't had the time to do that yet.
  • No rate limiter set for the moment so when fetching a bunch of item prices you could hit the rate limiter of poe.watch. I'll add one at some point in the future if is needed or requested.

Contribution

The code is well documented, using tomdoc, if you wish to contribute, raise an issue or fork this project and create a pull request :).

Most of the codebase is in lib/api, lib/base and lib/item.

License

Licensed under WTFPL.