Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding V2 stats as the main and moving V1 stats to their own V1 calls to be deprecated later #4

Open
wants to merge 39 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1091fb1
Added Proxy Support
Fyb3roptik Jan 30, 2019
a89d8cc
adjusting timeout
Fyb3roptik Jan 30, 2019
dc0a24c
Updated session to return error instead of panic
Fyb3roptik Feb 8, 2019
f0fcc71
session updates for err
Fyb3roptik Feb 8, 2019
b8db291
Adding V2 Stats for testing
Fyb3roptik Mar 18, 2019
d9ebdcd
fixing a couple of items for v2
Fyb3roptik Mar 18, 2019
618c336
fixing url
Fyb3roptik Mar 18, 2019
c7ab033
Adding completely new endpoint for V2
Fyb3roptik Mar 18, 2019
fe95c13
fixing the endpoint
Fyb3roptik Mar 18, 2019
f9cc69b
Trying to patch endpoint url
Fyb3roptik Mar 18, 2019
85b8988
Should fix the v2 stats endpoint finally
Fyb3roptik Mar 18, 2019
cc7ed02
Remapping V2 data to the Player model. There are no more platforms, s…
Fyb3roptik Mar 18, 2019
d818e8a
Fixing stats adding incorrectly
Fyb3roptik Mar 18, 2019
eff61d0
Adding some debugging for figuring out stat counter issue
Fyb3roptik Mar 18, 2019
9ac8f00
Added more debug logging
Fyb3roptik Mar 18, 2019
9544c74
moving debug log
Fyb3roptik Mar 18, 2019
20f1f81
Update epic.go
Fyb3roptik Mar 18, 2019
a4e2164
Potential fix for counting all stats as one
Fyb3roptik Mar 18, 2019
7959d41
small minor debug log move
Fyb3roptik Mar 18, 2019
54faa57
Update epic.go
Fyb3roptik Mar 18, 2019
bef2e9d
Patching v2 stats counter as well as added raw stats
Fyb3roptik Mar 18, 2019
10a5029
Updating all endpoints to V2. Updated README. Renamed package name to…
Fyb3roptik Mar 18, 2019
6e41c0b
Adding account info stuff back
Fyb3roptik Mar 18, 2019
f13b9b0
Adding support for V1 stats for backwards compatibility
Fyb3roptik Mar 19, 2019
b7c92a6
Adding 2FA endpoint, removing error string before json
Fyb3roptik May 7, 2019
420efc3
Adding 2FA login
Fyb3roptik May 7, 2019
3997204
Adding input type to the return stats
Fyb3roptik Jun 28, 2019
7fb5a0e
Patching a bug
Fyb3roptik Jun 28, 2019
0f83ae1
Updating README
Fyb3roptik Jun 28, 2019
dcfd025
Added last modified field to stats return for v2
Fyb3roptik Jul 23, 2019
f87af7e
AUTH updates
Fyb3roptik Sep 24, 2019
463e6d1
Patching client
Fyb3roptik Sep 25, 2019
b04abe0
Pushing updates
Fyb3roptik Sep 25, 2019
fffbf1f
Pushing updates
Fyb3roptik Sep 30, 2019
14f6668
Updating for 2fa
Fyb3roptik Oct 1, 2019
d6490df
Adding level and percent to next level
Fyb3roptik Nov 13, 2019
3a83daf
Adding check for privacy settings
Fyb3roptik Dec 5, 2019
a302dc6
Updating stats endpoint
Fyb3roptik Dec 5, 2019
af514bb
Making final Stats a pointer for nil check
Fyb3roptik Dec 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 137 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ To obtain header tokens:
* Launch Fortnite
* You will see again a request with _/account/api/oauth/token_. Click on it and then click `Inspectors` tab to get the header (Copy `Authorization` header content and remove "basic ") => **This header is your Game Token**

## V2 Stats
This package has been updated to the latest V2 stats from Epic. There are no more platforms. All stats are broken up between input type (keyboardmouse, gamepad, and touch).

## V1 Stats Compatibility - *Deprecated*
To retrieve stats via V1 stats, please use the QueryPlayerV1 method:

```go
// Retrieve player info and stats by Account ID.
player, err := s.QueryPlayerV1("", "AccountID")
if err != nil {
fmt.Println(err)
}
```

## Usage

See [Godoc](https://godoc.org/github.com/henhouse/fortnite-go) for in-depth documentation.
Expand All @@ -22,16 +36,16 @@ See [Godoc](https://godoc.org/github.com/henhouse/fortnite-go) for in-depth docu
To retrieve a player's information and statistics for Battle Royale:
```go
// Create the session.
sess := fornitego.Create("USERNAME", "PASSWORD", "LAUNCHER-TOKEN", "GAME-TOKEN")
sess := fortnitego.Create("USERNAME", "PASSWORD", "LAUNCHER-TOKEN", "GAME-TOKEN")

// Retrieve player info and stats by Username and Platform.
player, err := s.QueryPlayer("PlayerName", "", fornitego.PC) // (PC/Xbox/PS4)
// Retrieve player info and stats by Username.
player, err := s.QueryPlayer("PlayerName", "")
if err != nil {
fmt.Println(err)
}

// Retrieve player info and stats by Account ID and Platform.
player, err := s.QueryPlayer("", "AccountID", fornitego.PC) // (PC/Xbox/PS4)
// Retrieve player info and stats by Account ID.
player, err := s.QueryPlayer("", "AccountID")
if err != nil {
fmt.Println(err)
}
Expand All @@ -41,48 +55,130 @@ If the player exists, a result may look like the example below. (Represented in
{
"AccountInfo": {
"AccountID": "6cd40c1722f2497fa1d2145b26da88e3",
"Username": "WalterJr2",
"Platform": "pc"
},
"Stats": {
"Solo": {
"Wins": 23,
"Top10": 86,
"Top25": 154,
"KillDeathRatio": "3.13",
"WinPercentage": "6.74",
"Matches": 341,
"Kills": 995,
"MinutesPlayed": 2174,
"KillsPerMatch": "2.92",
"KillsPerMinute": "0.46",
"Score": 56247
"Touch": {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch back to spaces instead of tabs in here.

"Wins": 23,
"Top10": 86,
"Top25": 154,
"KillDeathRatio": "3.13",
"WinPercentage": "6.74",
"Matches": 341,
"Kills": 995,
"MinutesPlayed": 2174,
"KillsPerMatch": "2.92",
"KillsPerMinute": "0.46",
"Score": 56247
},
"Gamepad": {
"Wins": 23,
"Top10": 86,
"Top25": 154,
"KillDeathRatio": "3.13",
"WinPercentage": "6.74",
"Matches": 341,
"Kills": 995,
"MinutesPlayed": 2174,
"KillsPerMatch": "2.92",
"KillsPerMinute": "0.46",
"Score": 56247
},
"KeyboardMouse": {
"Wins": 23,
"Top10": 86,
"Top25": 154,
"KillDeathRatio": "3.13",
"WinPercentage": "6.74",
"Matches": 341,
"Kills": 995,
"MinutesPlayed": 2174,
"KillsPerMatch": "2.92",
"KillsPerMinute": "0.46",
"Score": 56247
},
},
"Duo": {
"Wins": 45,
"Top5": 89,
"Top12": 149,
"KillDeathRatio": "3.27",
"WinPercentage": "11.03",
"Matches": 408,
"Kills": 1186,
"MinutesPlayed": 1465,
"KillsPerMatch": "2.91",
"KillsPerMinute": "0.81",
"Score": 91499
"Touch": {
"Wins": 45,
"Top5": 89,
"Top12": 149,
"KillDeathRatio": "3.27",
"WinPercentage": "11.03",
"Matches": 408,
"Kills": 1186,
"MinutesPlayed": 1465,
"KillsPerMatch": "2.91",
"KillsPerMinute": "0.81",
"Score": 91499
},
"Gamepad": {
"Wins": 45,
"Top5": 89,
"Top12": 149,
"KillDeathRatio": "3.27",
"WinPercentage": "11.03",
"Matches": 408,
"Kills": 1186,
"MinutesPlayed": 1465,
"KillsPerMatch": "2.91",
"KillsPerMinute": "0.81",
"Score": 91499
},
"KeyboardMouse": {
"Wins": 45,
"Top5": 89,
"Top12": 149,
"KillDeathRatio": "3.27",
"WinPercentage": "11.03",
"Matches": 408,
"Kills": 1186,
"MinutesPlayed": 1465,
"KillsPerMatch": "2.91",
"KillsPerMinute": "0.81",
"Score": 91499
},
},
"Squad": {
"Wins": 116,
"Top3": 190,
"Top6": 305,
"KillDeathRatio": "3.60",
"WinPercentage": "14.23",
"Matches": 815,
"Kills": 2516,
"MinutesPlayed": 3143,
"KillsPerMatch": "3.09",
"KillsPerMinute": "0.80",
"Score": 253462
"Touch": {
"Wins": 116,
"Top3": 190,
"Top6": 305,
"KillDeathRatio": "3.60",
"WinPercentage": "14.23",
"Matches": 815,
"Kills": 2516,
"MinutesPlayed": 3143,
"KillsPerMatch": "3.09",
"KillsPerMinute": "0.80",
"Score": 253462
},
"Gamepad": {
"Wins": 116,
"Top3": 190,
"Top6": 305,
"KillDeathRatio": "3.60",
"WinPercentage": "14.23",
"Matches": 815,
"Kills": 2516,
"MinutesPlayed": 3143,
"KillsPerMatch": "3.09",
"KillsPerMinute": "0.80",
"Score": 253462
},
"KeyboardMouse": {
"Wins": 116,
"Top3": 190,
"Top6": 305,
"KillDeathRatio": "3.60",
"WinPercentage": "14.23",
"Matches": 815,
"Kills": 2516,
"MinutesPlayed": 3143,
"KillsPerMatch": "3.09",
"KillsPerMinute": "0.80",
"Score": 253462
},
}
}
}
Expand All @@ -91,7 +187,7 @@ If the player exists, a result may look like the example below. (Represented in
### Leaderboard
To retrieve the top 50 global wins leaderboard:
```go
lb, err := sess.GetWinsLeaderboard(fornitego.PC, fornitego.Squad) // (Solo, Duo, Squad)
lb, err := sess.GetWinsLeaderboard(fortnitego.PC, fortnitego.Squad) // (Solo, Duo, Squad)
if err != nil {
fmt.Println(err)
}
Expand Down
31 changes: 19 additions & 12 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package fornitego
package fortnitego

import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"runtime"
)

Expand All @@ -26,7 +28,8 @@ var userAgent = fmt.Sprintf(

func newClient() *Client {
// Return default HTTP client for now. @todo replace with defined client
return &Client{client: &http.Client{}}
cookieJar, _ := cookiejar.New(nil)
return &Client{client: &http.Client{Jar: cookieJar}}
}

// NewRequest prepares a new HTTP request and sets the necessary headers.
Expand Down Expand Up @@ -55,43 +58,47 @@ var (
)

// Do processes a prepared HTTP request with the client provided. An interface is passed in to decode the response into.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, int, error) {
// Process request using session's client. Collect response.
resp, err := c.client.Do(req)
if err != nil {
return nil, err
log.Println("ERR: ", err)
return nil, 0, err
}

// Check response status codes to determine success/failure.
err = checkStatus(resp)
status_code, err := checkStatus(resp)
if err != nil {
return nil, err
return nil, status_code, err
}

// If an interface was provided, decode response body into it.
if v != nil {
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil && err != io.EOF {
return resp, err
log.Println("ERR: ", err)
return resp, 0, err
}
}

return resp, nil
return resp, 0, nil
}

// checkStatus checks the HTTP response status code for unsuccessful requests.
// @todo decode error into Epic Error-JSON object to determine better errors.go?
func checkStatus(resp *http.Response) error {
func checkStatus(resp *http.Response) (int, error) {
switch resp.StatusCode {
case http.StatusOK, http.StatusNoContent:
return nil
return 0, nil
default:
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.New("unsuccessful response returned and cannot read body: " + err.Error())
return 0, errors.New("unsuccessful response returned and cannot read body: " + err.Error())
}
defer resp.Body.Close()

return errors.New(fmt.Sprintf("unsuccessful response returned: %v %v", resp.StatusCode, string(b)))
status_code := resp.StatusCode

return status_code, errors.New(string(b))
}
}
Loading