gohltb

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2020 License: MIT Imports: 10 Imported by: 0

README

= gohltb (go howlongtobeat.com)
:toc:
:toclevels: 5

gohltb is an unofficial cli tool and go library for the website howlongtobeat.com.
It provides an aggregated view of user completion times for video games.

== Usage
gohltb can both be used as a library as well as a standalone CLI tool, here's how
to use both of them.

=== CLI Tool
The CLI tool is a very simple query implementation of the library. As of this time,
it doesn't do a whole lot:

. Takes in a set of user query parameters (i.e. game title, user name).
. Prints out a JSON conversion of the result data to the console.
.. Response Data is always paged, and only current page will be printed.
. That's it.

.CLI usage
----
% ./gohltb -h          
Usage of ./gohltb:
  -d    Include additional user details when querying games.
  -q string
        Query string. This will be the game title if searching for games, or user name if searching for users.
  -r    Return a single, random, game or user.
  -s string
        How the response should be sorted. Sorts by name by default.
        Games support: name, main, mainp, comp, averagea, rating, popular, backlog, usersp, playing, speedruns, release
        Users support: name, gender, postcount, numcomp, numbacklog (default "name")
  -u    Query users instead of games
----

==== Query for game

.basic game query
----
% ./gohltb -g "Mario" -r -d
[
  {
    "id": "9361",
    "title": "Super Mario 3D Land",
    "url": "https://howlongtobeat.com/game?id=9361",
    "box-art-url": "https://howlongtobeat.com/games/250px-Super-Mario-3D-Land-Logo.jpg",
    "main": "7 Hours",
    "main-extra": "12½ Hours",
    "completionist": "22½ Hours",
    "user-stats": {
      "completed": "2.5K",
      "rating": "81% by 940",
      "backlog": "1.1K",
      "playing": "200",
      "retired": "78",
      "speedruns": "5"
    }
  }
]
----

.basic user query
----
% ./gohltb -g "Bob" -r -u
[
  {
    "id": "BobGamingHD",
    "name": "BobGamingHD",
    "url": "https://howlongtobeat.com/user?n=BobGamingHD",
    "avatar-url": "https://howlongtobeat.com/avatars/no_avatar.png",
    "complete": "0"
  }
]
----

=== Package

==== Quick Start
1. Add `require "github.com/fuzzylimes/gohltb" latest` to your `go.mod` file
2. Run `go get` to pick up package
3. Create a new `HLTBClient` by using `client := gohltb.NewDefaultClient()`
4. Search for game using `client.SearchGames("title")`

===== Example

.main.go
[source,golang]
----
package main

import (
	"fmt"
	"log"

	"github.com/fuzzylimes/gohltb"
)

func main() {
  client := gohltb.NewDefaultClient()
	games, err := client.SearchGames("pokemon")
	if err != nil {
		log.Fatal(err)
	}
	j, err := games.JSON()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(j)
}
----

==== Making a Query
There are two main ways to create a query: general search or a detailed query. A version
of these queries exist for both games and users. The available methods are:

. `SearchGames` - searches for a specific game title, using default query parameters
. `SearchUsers` - searches for a specific user name, using default query parameters
. `SearchGamesByQuery` - searches for games using `HLTBQuery` object
. `SearchUsersByQuery` - searches for users using `HLTBQuery` object

The quick start example above is the most basic example of a request that you can make
using gohltb. It's intended to be used when you simply want to query for a game by a
title, and you don't care about much of anything else. While the example shows how
to do a game query, a user query would be done by swapping out `SearchGames` with
`SearchUsers`.

If you're looking to define a more specific query, you would want to use one of the
`SearchByQuery` methods. This takes in a `HLTBQuery` with your specified query parameters.
Both Game and User queries utilize the same `HLTBQuery` object, but the supported
parameters vary for each. It's important to note that many of the parameters used expect
specific types. These types and all of their possible options are already available in
the `constants.go` file.

[NOTE]
Every query parameter is optional. You do not need to include any parameters that
you do not care about. Any mandatory defaults are handled when values are not present.

The table below shows the mapping for the query parameters. Note that a reference to
(constant) means that it expects one of the constant values defined in the `constants.go`
file:

.Query Parameters
|===
|Parameter |Definition |Game Query | User Query

|Query
|String to query by
|Game title
|User name

|QueryType (constant)
|Type of query to perform - games or users
|GameQuery
|UserQuery

|SortBy (constant)
|Specify how data should be sorted
|Supported "SortByGame"
|Supported "SortByUser"

|SortDirection (constant)
|Specify direction data should be sorted
|Supported SortDirection
|Supported SortDirection

|Platform (constant)
|Platform to query against (only used with game queries)
|Supported Platform
|---

|LengthType (constant)
|Optional filter based on completion times (games only)
|Supported LengthType
|---

|LengthMin (constant)
|Optional min length for LengthType (games only)
|Supported LengthMin
|---

|LengthMax (constant)
|Optional max length for LengthType (games only)
|Supported LengthMax
|---

|Modifier (constant)
|Toggle additional filter methods (games only)
|Supported Modifier
|---

|Random
|Return a single, random, entry based on parameters
|true,false
|true,false

|Page
|Page number to return
|int
|int

|===

==== Handling Response
All response data returned from queries is paginated. Because of this, each response
objet comes with a set of helper methods to handle the response data:

- `.JSON()` - convert response data to a JSON string
- `.HasNext()` - check if there's a next page
- `.GetNext()` - queries for the next page of data, if it exists

=== Examples
==== Query for Metal Gear Solid games on Playstation 2
[source,golang]
----
func main() {
  client := gohltb.NewDefaultClient()
  query := &HLTBQuery{Query: "Metal Gear Solid", Platform: PlayStation2, SortBy: SortByGameMostPopular}
	games, err := client.SearchGamesByQuery(query)
	if err != nil {
		log.Fatal(err)
	}
	j, err := games.JSON()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(j)
}
----

==== Query for all GameBoy games, sorted by release date, newest first
[source,golang]
----
func main() {
  client := gohltb.NewDefaultClient()
  query := &HLTBQuery{Platform: GameBoy, SortBy: SortByGameReleaseDate, SortDirection: ReverseOrder},
	games, err := client.SearchGamesByQuery(query)
	if err != nil {
		log.Fatal(err)
	}
	j, err := games.JSON()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(j)
  if games.HasNext() {
    games, err = games.GetNext()
  }
}
----

==== Query for all Users named Bob, sorted by number of completed games
[source,golang]
----
func main() {
  client := gohltb.NewDefaultClient()
  query := &HLTBQuery{Query: "Bob", SortBy: SortByUserCompleted},
	users, err := client.SearchUsersByQuery(query)
	if err != nil {
		log.Fatal(err)
	}
	j, err := users.JSON()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(j)
  if users.HasNext() {
    users, err = users.GetNext()
  }
}
----

=== Disclaimer

====
I am not associated with `howlongtobeat.com` in any way, shape, or form. The data collected by this tool/package all belongs to the owner(s) of `howlongtobeat.com`. If you are the owner and would like this tool/library removed, please reach out!
====

Documentation

Index

Constants

View Source
const (
	ThreeDO          Platform = "3DO"
	Amiga            Platform = "Amiga"
	AmstradCPC       Platform = "Amstrad CPC"
	Android          Platform = "Android"
	AppleII          Platform = "Apple II"
	Arcade           Platform = "Arcade"
	Atari2600        Platform = "Atari 2600"
	Atari5200        Platform = "Atari 5200"
	Atari7800        Platform = "Atari 7800"
	Atari8bitFamily  Platform = "Atari 8-bit Family"
	AtariJaguar      Platform = "Atari Jaguar"
	AtariJaguarCD    Platform = "Atari Jaguar CD"
	AtariLynx        Platform = "Atari Lynx"
	AtariST          Platform = "Atari ST"
	BBCMicro         Platform = "BBC Micro"
	Browser          Platform = "Browser"
	ColecoVision     Platform = "ColecoVision"
	Commodore64      Platform = "Commodore 64"
	Dreamcast        Platform = "Dreamcast"
	Emulated         Platform = "Emulated"
	FMTowns          Platform = "FM Towns"
	GameWatch        Platform = "Game & Watch"
	GameBoy          Platform = "Game Boy"
	GameBoyAdvance   Platform = "Game Boy Advance"
	GameBoyColor     Platform = "Game Boy Color"
	GearVR           Platform = "Gear VR"
	GoogleStadia     Platform = "Google Stadia"
	Intellivision    Platform = "Intellivision"
	InteractiveMovie Platform = "Interactive Movie"

	Linux                Platform = "Linux"
	Mac                  Platform = "Mac"
	Mobile               Platform = "Mobile"
	MSX                  Platform = "MSX"
	NGage                Platform = "N-Gage"
	NECPC8800            Platform = "NEC PC-8800"
	NECPC980121          Platform = "NEC PC-9801/21"
	NECPCFX              Platform = "NEC PC-FX"
	NeoGeo               Platform = "Neo Geo"
	NeoGeoCD             Platform = "Neo Geo CD"
	NeoGeoPocket         Platform = "Neo Geo Pocket"
	NES                  Platform = "NES"
	Nintendo3DS          Platform = "Nintendo 3DS"
	Nintendo64           Platform = "Nintendo 64"
	NintendoDS           Platform = "Nintendo DS"
	NintendoGameCube     Platform = "Nintendo GameCube"
	NintendoSwitch       Platform = "Nintendo Switch"
	OculusGo             Platform = "Oculus Go"
	OculusQuest          Platform = "Oculus Quest"
	OnLive               Platform = "OnLive"
	Ouya                 Platform = "Ouya"
	PC                   Platform = "PC"
	PCVR                 Platform = "PC VR"
	PhilipsCDi           Platform = "Philips CD-i"
	PhilipsVideopacG7000 Platform = "Philips Videopac G7000"
	PlayStation          Platform = "PlayStation"
	PlayStation2         Platform = "PlayStation 2"
	PlayStation3         Platform = "PlayStation 3"
	PlayStation4         Platform = "PlayStation 4"
	PlayStation5         Platform = "PlayStation 5"
	PlayStationMobile    Platform = "PlayStation Mobile"
	PlayStationNow       Platform = "PlayStation Now"
	PlayStationPortable  Platform = "PlayStation Portable"
	PlayStationVita      Platform = "PlayStation Vita"
	PlayStationVR        Platform = "PlayStation VR"
	PlugPlay             Platform = "Plug & Play"
	Sega32X              Platform = "Sega 32X"
	SegaCD               Platform = "Sega CD"
	SegaGameGear         Platform = "Sega Game Gear"
	SegaMasterSystem     Platform = "Sega Master System"
	SegaMegaDriveGenesis Platform = "Sega Mega Drive/Genesis"
	SegaSaturn           Platform = "Sega Saturn"
	SG1000               Platform = "SG-1000"
	SharpX68000          Platform = "Sharp X68000"
	SuperNintendo        Platform = "Super Nintendo"
	TigerHandheld        Platform = "Tiger Handheld"
	TurboGrafx16         Platform = "TurboGrafx-16"
	TurboGrafxCD         Platform = "TurboGrafx-CD"
	VirtualBoy           Platform = "Virtual Boy"
	Wii                  Platform = "Wii"
	WiiU                 Platform = "Wii U"
	WindowsPhone         Platform = "Windows Phone"
	WonderSwan           Platform = "WonderSwan"
	Xbox                 Platform = "Xbox"
	Xbox360              Platform = "Xbox 360"
	XboxOne              Platform = "Xbox One"
	XboxSeriesXS         Platform = "Xbox Series X/S"
	ZXSpectrum           Platform = "ZX Spectrum"

	// SortByGameName sorts by game title - default
	SortByGameName SortBy = "name"
	// SortByGameMainStory sorts by the main story competion time (shortest to longest)
	SortByGameMainStory SortBy = "main"
	// SortByGameMainExtras sorts by the main + extras competion time (shortest to longest)
	SortByGameMainExtras SortBy = "mainp"
	// SortByGameCompletionist sorts by the completionist competion time (shortest to longest)
	SortByGameCompletionist SortBy = "comp"
	// SortByGameAverageTime sorts by the average competion time (shortest to longest)
	SortByGameAverageTime SortBy = "averagea"
	// SortByGameTopRated sorts by games with the highest user rating (highest to lowest)
	SortByGameTopRated SortBy = "rating"
	// SortByGameMostPopular sorts by games that have been added by the most number of users
	SortByGameMostPopular SortBy = "popular"
	// SortByGameMostBacklogs sorts by the number of users with the game in their backlog
	SortByGameMostBacklogs SortBy = "backlog"
	// SortByGameMostSubmissions sorts by the number of user submissions (submitted a time)
	SortByGameMostSubmissions SortBy = "usersp"
	// SortByGameMostPlayed sorts by the number of users that have completed the game
	SortByGameMostPlayed SortBy = "playing"
	// SortByGameMostSpeedruns sorts by the number of submitted speedruns for a game
	// (note that these are the speed runs submitted to howlongtobeat.com, not speedrun.com)
	SortByGameMostSpeedruns SortBy = "speedruns"
	// SortByGameReleaseDate sorts by the release date of the game (earliest to most recent)
	SortByGameReleaseDate SortBy = "release"

	// SortByUserTopPosters will sort by the most active comunity members
	SortByUserTopPosters SortBy = "postcount"
	// SortByUserName will sort by user's display name
	SortByUserName SortBy = "name"
	// SortByUserGender will sort by user's gender
	SortByUserGender SortBy = "gender"
	// SortByUserCompleted will sort by user's number of completed games
	SortByUserCompleted SortBy = "numcomp"
	// SortByUserBacklog will sort by user's number of games in their backlog
	SortByUserBacklog SortBy = "numbacklog"

	// RangeMainStory will search Main Story completion times
	RangeMainStory LengthRange = "main"
	// RangeMainExtras will search Main + Extra completion times
	RangeMainExtras LengthRange = "mainp"
	// RangeCompletionist will search Completionist completion times
	RangeCompletionist LengthRange = "comp"
	// RangeAverageTime will search average completion times
	RangeAverageTime LengthRange = "averagea"

	// NoModifier will use no search modifiers
	NoModifier Modifier = ""
	// IncludeDLC will show DLC in responses
	IncludeDLC Modifier = "show_dlc"
	// IsolateDLC will only return DCL in responses
	IsolateDLC Modifier = "only_dlc"

	// ShowUserStats will include user stats in responses
	ShowUserStats Modifier = "user_stats"

	// NormalOrder sorts in the direction specified by the SortBy method
	NormalOrder SortDirection = "Normal Order"
	// ReverseOrder sorts in the reverse direction specified by the SortBy method
	ReverseOrder SortDirection = "Reverse Order"

	// GameQuery will query against game titles
	GameQuery QueryType = "games"
	// UserQuery will query against user names
	UserQuery QueryType = "users"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type GameResult

type GameResult struct {
	ID            string            `json:"id"`                   // ID in howlongtobeat.com's database
	Title         string            `json:"title"`                // Title of game
	URL           string            `json:"url"`                  // Link to game page
	BoxArtURL     string            `json:"box-art-url"`          // Link to boxart
	Main          string            `json:"main"`                 // Completion time for Main category
	MainExtra     string            `json:"main-extra"`           // Completion time for Main + Extra category
	Completionist string            `json:"completionist"`        // Completion time for Completionist category
	Other         map[string]string `json:"other,omitempty"`      // Times that don't fall under the main 3 time categories
	UserStats     *UserStats        `json:"user-stats,omitempty"` // Optional additional user details (only present when requested)
}

GameResult are the data object for Games. Games contain the thing that you're probably most interested in, which are the completion times. All of the times that are collected are presented as strings, you will need to handle any kind of conversions if you need them as numbers.

Completion times break down as:

  • Main - time to complete the main game
  • MainExtra - time to complete the main game and all extras
  • Completionist - time to 100% the game
  • Other - These are other kinds of times, primarily reserved for multiplayer games

type GameResultsPage

type GameResultsPage struct {
	Games        []*GameResult `json:"games"`       // Slice of GameResult
	TotalPages   int           `json:"total-pages"` // Total number of pages
	CurrentPage  int           `json:"curent-page"` // Current page number
	NextPage     int           `json:"next-page"`   // Next page number
	TotalMatches int           `json:"matches"`     // Total query matches
	// contains filtered or unexported fields
}

GameResultsPage is a page of game responses. It is the data model that will be returned for any Game query. Provides ability to move between pages of Game results.

func (*GameResultsPage) GetNextPage

func (g *GameResultsPage) GetNextPage() (*GameResultsPage, error)

GetNextPage will return the next page, if it exists. Uses the client from the initial request to make additional queries.

func (*GameResultsPage) HasNext

func (g *GameResultsPage) HasNext() bool

HasNext will check to see if there is a next page that can be retrieved

func (*GameResultsPage) JSON

func (g *GameResultsPage) JSON() (string, error)

JSON will convert a game object into a json string

type HLTBClient

type HLTBClient struct {
	Client *HTTPClient
}

HLTBClient is the main client used to interact with the APIs. You should be creating a client via one of the two "New" methods, either NewDefaultClient or NewCustomClient. Either will be needed to perform game or user queries.

func NewCustomClient

func NewCustomClient(c *HTTPClient) *HLTBClient

NewCustomClient will create a new HLTBClient with provided HTTPClient. Users are able to pass in an HTTPClient with their desired http.Client.

func NewDefaultClient

func NewDefaultClient() *HLTBClient

NewDefaultClient will create a new HLTBClient with default parameters. This is what you should use to create you client if you don't need to use a specific http.Client/settings

func (*HLTBClient) SearchGames

func (h *HLTBClient) SearchGames(query string) (*GameResultsPage, error)

SearchGames performs a search for the provided game title. Will populate default values for the reamaining query parameters, aside from the provided game title.

Note: A query with an empty query string will query ALL games

func (*HLTBClient) SearchGamesByQuery

func (h *HLTBClient) SearchGamesByQuery(q *HLTBQuery) (*GameResultsPage, error)

SearchGamesByQuery queries using a set of user defined parameters. Used for running more complex queries. Takes in a HLTBQuery object, with parameters tailored to a user query. You may include any of the following:

  • Query - user name
  • QueryType - UserQuery
  • SortBy - one of the various "SortByUser" options
  • SortDirection - sort direcion, based on SortBy
  • Platform - restrict responses to platform (see constants.go)
  • LengthType - Type of length parameter to (optionally) fillter by
  • LengthMax - Max value for LengthType
  • LengthMin - Min value for LengthType
  • Modifier - Optional additional query parameters.
  • Random - whether or not to retrieve random value
  • Page - page of responses to return

Note: A query with an empty "Query" string will query ALL games.

func (*HLTBClient) SearchUsers

func (h *HLTBClient) SearchUsers(query string) (*UserResultsPage, error)

SearchUsers performs a search for the provided user name. Will populate default values for the remaining query parameters aside from the provided user name.

Note: A query with an empty string will query ALL users.

func (*HLTBClient) SearchUsersByQuery

func (h *HLTBClient) SearchUsersByQuery(q *HLTBQuery) (*UserResultsPage, error)

SearchUsersByQuery queries using a set of user defined parameters. Used for running more complex queries. Takes in a HLTBQuery object, with parameters tailored to a user query. You may include any of the following:

  • Query - user name
  • QueryType - UserQuery
  • SortBy - one of the various "SortByUser" options
  • SortDirection - sort direcion, based on SortBy
  • Random - whether or not to retrieve random value
  • Page - page of responses to return

Note: A query with an empty "Query" string will query ALL users.

type HLTBQuery

type HLTBQuery struct {
	Query         string        // String to query by
	QueryType     QueryType     // Type of query to perform - games or users
	SortBy        SortBy        // Specify how data should be sorted
	SortDirection SortDirection // Specify direction data should be sorted
	Platform      Platform      // Platform to query against (only used with game queries)
	LengthType    LengthRange   // Optional filter based on completion times (games only)
	LengthMin     string        // Optional min length for LengthType (games only)
	LengthMax     string        // Optional max length for LengthType (games only)
	Modifier      Modifier      // Toggle additional filter methods (games only)
	Random        bool          // Return a single, random, entry based on parameters
	Page          int           // Page number to return
}

HLTBQuery is a query object used to run user defined queries. Both game and user queries both use the HLTBQuery as their means of query. The library handles any mandatory parameters for you, making all parameters optional when constructing a query.

example: client.SearchGamesByQuery(&HLTBQuery{query: "Mario", random: true})

type HTTPClient

type HTTPClient struct {
	Client *http.Client
	// contains filtered or unexported fields
}

HTTPClient handles the connectivity details for the client. This is handled automatically when using the NewDefaultClient constructor, but can optionally be supplied when creating a NewCustomClient. This allows the user to create their own http.Client and pass it in for use. This can be useful if you want to use something other than the default configuration.

type LengthRange

type LengthRange string

LengthRange allows filtering by the time it takes to complete a game

type Modifier

type Modifier string

Modifier is additional information to be included in response

type Pages

type Pages interface {
	// contains filtered or unexported methods
}

Pages are a type of data structure for paged responses.

type Platform

type Platform string

Platform is where the game is played (i.e. console, operating system)

type QueryType

type QueryType string

QueryType is the subject being queried

type SortBy

type SortBy string

SortBy is how the response will be sorted

type SortDirection

type SortDirection string

SortDirection specifies the direction the responses will be sorted (baed on SortBy)

type UserResult

type UserResult struct {
	ID        string   `json:"id"`                  // ID in howlongtobeat.com's database
	Name      string   `json:"name"`                // User's display name
	URL       string   `json:"url"`                 // Link to user's page
	AvatarURL string   `json:"avatar-url"`          // Link to avatar
	Location  string   `json:"location,omitempty"`  // User's location
	Backlog   string   `json:"backlog,omitempty"`   // Number of games in user's backlog
	Complete  string   `json:"complete,omitempty"`  // Number of games the user's completed
	Gender    string   `json:"gender,omitempty"`    // User's gender
	Posts     string   `json:"posts,omitempty"`     // Number of user's forum posts
	Age       int      `json:"age,omitempty"`       // User's age
	Accolades []string `json:"accolades,omitempty"` // User accolades for activity on the site. This is things like years of service.
}

UserResult are the data object for Users. They contain information about a user that can be collected from the user query response. Users are the people on howlongtobeat.com that contribute completion times to the site or track their game collections.

type UserResultsPage

type UserResultsPage struct {
	Users        []*UserResult `json:"users"`       // Slice of UserResult
	TotalPages   int           `json:"total-pages"` // Total number of pages
	CurrentPage  int           `json:"curent-page"` // Current page number
	NextPage     int           `json:"next-page"`   // Next page number
	TotalMatches int           `json:"matches"`     // Total query matches
	// contains filtered or unexported fields
}

UserResultsPage is a page of user responses. It is the data model that will be returned for any User query. Provides ability to move between pages of User results.

func (*UserResultsPage) GetNextPage

func (u *UserResultsPage) GetNextPage() (*UserResultsPage, error)

GetNextPage will return the next page, if it exists. Uses the client from the initial request to make additional queries.

func (*UserResultsPage) HasNext

func (u *UserResultsPage) HasNext() bool

HasNext will check to see if there is a next page that can be retrieved

func (*UserResultsPage) JSON

func (u *UserResultsPage) JSON() (string, error)

JSON will convert user object into a json string

type UserStats

type UserStats struct {
	Completed string `json:"completed,omitempty"` // Number of users that have marked the game as Completed
	Rating    string `json:"rating,omitempty"`    // Average User rating
	Backlog   string `json:"backlog,omitempty"`   // Number of users that have placed game in their backlog
	Playing   string `json:"playing,omitempty"`   // Number of users that are currently playing through a game
	Retired   string `json:"retired,omitempty"`   // Number of users that did not finish a game
	SpeedRuns string `json:"speedruns,omitempty"` // Number of users that have submitted speedruns for the game
}

UserStats are additional stats based on user activity on howlongtobeat.com This information is only included when additional user details are requested, by setting the Modifier in HLTBQuery to ShowUserStats

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL