Skip to content

Commit

Permalink
Make requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
cosrnic authored and mworzala committed Oct 6, 2024
1 parent 12fbe4c commit dc589d1
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 175 deletions.
8 changes: 4 additions & 4 deletions cmd/mc/skin/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ func (o *addSkinOpts) execute(args []string) error {
return err
}

client := mojang.NewProfileClient(o.app.Build.Version)
client := mojang.NewProfileClient(o.app.Build.Version, token)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()

info, err := client.ProfileInformation(ctx, token)
info, err := client.ProfileInformation(ctx)
if err != nil {
return err
}
Expand All @@ -112,14 +112,14 @@ func (o *addSkinOpts) execute(args []string) error {

skinData := args[0]

skin, err := o.app.SkinManager().CreateSkin(o.name, o.variant, skinData, o.cape, client, ctx)
skin, err := o.app.SkinManager().CreateSkin(ctx, client, o.name, o.variant, skinData, o.cape)
if err != nil {
return err
}

if o.apply {

err = o.app.SkinManager().ApplySkin(skin, client, ctx, token)
err = o.app.SkinManager().ApplySkin(ctx, client, skin)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/mc/skin/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ func (o *applySkinOpts) execute(args []string) error {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()

client := mojang.NewProfileClient(o.app.Build.Version)
client := mojang.NewProfileClient(o.app.Build.Version, token)

err = o.app.SkinManager().ApplySkin(skin, client, ctx, token)
err = o.app.SkinManager().ApplySkin(ctx, client, skin)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions internal/pkg/modrinth/modrinth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import (
"net/http"
"net/url"
"time"

"github.com/mworzala/mc/internal/pkg/util"
)

const (
userAgentFormat = "mworzala/mc/%s"

fabricApiProjectId = "P7dR8mSH"
)

Expand All @@ -31,7 +31,7 @@ type Client struct {
func NewClient(idVersion string) *Client {
return &Client{
baseUrl: prodUrl,
userAgent: fmt.Sprintf(userAgentFormat, idVersion),
userAgent: util.MakeUserAgent(idVersion),
httpClient: http.DefaultClient,
timeout: 10 * time.Second,
}
Expand All @@ -40,7 +40,7 @@ func NewClient(idVersion string) *Client {
func NewStagingClient() *Client {
return &Client{
baseUrl: stagingUrl,
userAgent: fmt.Sprintf(userAgentFormat, "dev"),
userAgent: util.MakeUserAgent("dev"),
httpClient: http.DefaultClient,
timeout: 10 * time.Second,
}
Expand Down
169 changes: 36 additions & 133 deletions internal/pkg/mojang/mojang.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,44 @@ import (
"io"
"net/http"
"time"
)

const (
userAgentFormat = "mworzala/mc/%s"
"github.com/mworzala/mc/internal/pkg/util"
)

var (
mojangApiUrl = "https://api.mojang.com/"
sessionserverUrl = "https://sessionserver.mojang.com/"
servicesApiUrl = "https://api.minecraftservices.com/"
profileApiUrl = servicesApiUrl + "minecraft/profile"
mojangApiUrl = "https://api.mojang.com"
sessionserverUrl = "https://sessionserver.mojang.com"
servicesApiUrl = "https://api.minecraftservices.com"
profileApiUrl = servicesApiUrl + "/minecraft/profile"
)

type Client struct {
baseUrl string
userAgent string
httpClient *http.Client
timeout time.Duration
baseUrl string
userAgent string
accountToken string
httpClient *http.Client
timeout time.Duration
}

func NewProfileClient(idVersion string) *Client {
func NewProfileClient(idVersion string, accountToken string) *Client {
return &Client{
baseUrl: profileApiUrl,
userAgent: fmt.Sprintf(userAgentFormat, idVersion),
httpClient: http.DefaultClient,
timeout: 10 * time.Second,
baseUrl: profileApiUrl,
userAgent: util.MakeUserAgent(idVersion),
accountToken: accountToken,
httpClient: http.DefaultClient,
timeout: 10 * time.Second,
}
}

func get[T any](c *Client, ctx context.Context, endpoint string, headers http.Header) (*T, error) {
func do[T any](c *Client, ctx context.Context, method string, url string, headers http.Header, body io.Reader) (*T, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()

fullUrl := fmt.Sprintf("%s%s", c.baseUrl, endpoint)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fullUrl, nil)
req, err := http.NewRequestWithContext(ctx, method, url, body)
if err != nil {
return nil, err
}

req.Header = headers
req.Header.Set("User-Agent", c.userAgent)

Expand All @@ -61,6 +61,12 @@ func get[T any](c *Client, ctx context.Context, endpoint string, headers http.He
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("401 %s: %s", errorRes.Path, errorRes.ErrorMessage)
} else if res.StatusCode == http.StatusBadRequest {
var errorRes badRequestError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("400 %s: %s", errorRes.Path, errorRes.Error)
} else if res.StatusCode == http.StatusNotFound {
var errorRes notFoundError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
Expand All @@ -80,127 +86,24 @@ func get[T any](c *Client, ctx context.Context, endpoint string, headers http.He
return &result, nil
}

func delete[T any](c *Client, ctx context.Context, endpoint string, headers http.Header) (*T, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()

fullUrl := fmt.Sprintf("%s%s", c.baseUrl, endpoint)
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fullUrl, nil)
if err != nil {
return nil, err
}
req.Header = headers
req.Header.Set("User-Agent", c.userAgent)

res, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()

if res.StatusCode == http.StatusUnauthorized {
var errorRes unauthorizedError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("401 %s: %s", errorRes.Path, errorRes.ErrorMessage)
} else if res.StatusCode == http.StatusInternalServerError {
return nil, errors.New("500 internal server error")
} else if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected response from server: %d", res.StatusCode)
}
func get[T any](c *Client, ctx context.Context, endpoint string, headers http.Header) (*T, error) {
url := c.baseUrl + endpoint
return do[T](c, ctx, http.MethodGet, url, headers, nil)
}

var result T
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return &result, nil
func delete[T any](c *Client, ctx context.Context, endpoint string, headers http.Header) (*T, error) {
url := c.baseUrl + endpoint
return do[T](c, ctx, http.MethodDelete, url, headers, nil)
}

func post[T any](c *Client, ctx context.Context, endpoint string, headers http.Header, body io.Reader) (*T, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()

fullUrl := fmt.Sprintf("%s%s", c.baseUrl, endpoint)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullUrl, body)
if err != nil {
return nil, err
}
req.Header = headers
req.Header.Set("User-Agent", c.userAgent)

res, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()

if res.StatusCode == http.StatusUnauthorized {
var errorRes unauthorizedError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("401 %s: %s", errorRes.Path, errorRes.ErrorMessage)
} else if res.StatusCode == http.StatusBadRequest {
var errorRes badRequestError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("400 %s: %s", errorRes.Path, errorRes.Error)
} else if res.StatusCode == http.StatusInternalServerError {
return nil, errors.New("500 internal server error")
} else if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected response from server: %d", res.StatusCode)
}

var result T
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return &result, nil
url := c.baseUrl + endpoint
return do[T](c, ctx, http.MethodPost, url, headers, body)
}

func put[T any](c *Client, ctx context.Context, endpoint string, headers http.Header, body io.Reader) (*T, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()

fullUrl := fmt.Sprintf("%s%s", c.baseUrl, endpoint)
req, err := http.NewRequestWithContext(ctx, http.MethodPut, fullUrl, body)
if err != nil {
return nil, err
}
req.Header = headers
req.Header.Set("User-Agent", c.userAgent)

res, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()

if res.StatusCode == http.StatusUnauthorized {
var errorRes unauthorizedError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("401 %s: %s", errorRes.Path, errorRes.ErrorMessage)
} else if res.StatusCode == http.StatusBadRequest {
var errorRes badRequestError
if err := json.NewDecoder(res.Body).Decode(&errorRes); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return nil, fmt.Errorf("400 %s: %s", errorRes.Path, errorRes.Error)
} else if res.StatusCode == http.StatusInternalServerError {
return nil, errors.New("500 internal server error")
} else if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected response from server: %d", res.StatusCode)
}

var result T
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode response body: %w", err)
}
return &result, nil
url := c.baseUrl + endpoint
return do[T](c, ctx, http.MethodPut, url, headers, body)
}

type unauthorizedError struct {
Expand Down
38 changes: 15 additions & 23 deletions internal/pkg/mojang/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ func isURL(s string) bool {
return err == nil && (u.Scheme == "http" || u.Scheme == "https")
}

func (c *Client) ProfileInformation(ctx context.Context, accountToken string) (*ProfileInformationResponse, error) {
func (c *Client) ProfileInformation(ctx context.Context) (*ProfileInformationResponse, error) {

headers := http.Header{}

headers.Set("Authorization", "Bearer "+accountToken)
headers.Set("Authorization", "Bearer "+c.accountToken)

return get[ProfileInformationResponse](c, ctx, "", headers)
return get[ProfileInformationResponse](c, ctx, "/", headers)
}

func (c *Client) ChangeSkin(ctx context.Context, accountToken string, texture string, variant string) (*ProfileInformationResponse, error) {
func (c *Client) ChangeSkin(ctx context.Context, texture string, variant string) (*ProfileInformationResponse, error) {
var body *bytes.Buffer
var contentType string

Expand Down Expand Up @@ -76,15 +76,15 @@ func (c *Client) ChangeSkin(ctx context.Context, accountToken string, texture st
headers := http.Header{}

headers.Set("Content-Type", contentType)
headers.Set("Authorization", "Bearer "+accountToken)
headers.Set("Authorization", "Bearer "+c.accountToken)

return post[ProfileInformationResponse](c, ctx, "/skins", headers, body)
}

func (c *Client) ChangeCape(ctx context.Context, accountToken string, cape string) (*ProfileInformationResponse, error) {
endpoint := "capes/active"
func (c *Client) ChangeCape(ctx context.Context, cape string) (*ProfileInformationResponse, error) {
endpoint := "/capes/active"
headers := http.Header{}
headers.Set("Authorization", "Bearer "+accountToken)
headers.Set("Authorization", "Bearer "+c.accountToken)
headers.Set("Content-Type", "application/json")

requestData := map[string]string{
Expand All @@ -99,30 +99,22 @@ func (c *Client) ChangeCape(ctx context.Context, accountToken string, cape strin
return put[ProfileInformationResponse](c, ctx, endpoint, headers, bytes.NewBuffer(jsonData))
}

func (c *Client) DeleteCape(ctx context.Context, accountToken string) (*ProfileInformationResponse, error) {
endpoint := "capes/active"
func (c *Client) DeleteCape(ctx context.Context) (*ProfileInformationResponse, error) {
endpoint := "/capes/active"
headers := http.Header{}
headers.Set("Authorization", "Bearer "+accountToken)
headers.Set("Authorization", "Bearer "+c.accountToken)

return delete[ProfileInformationResponse](c, ctx, endpoint, headers)
}

func (c *Client) UsernameToUuid(ctx context.Context, username string) (*UsernameToUuidResponse, error) {
oldUrl := c.baseUrl
c.baseUrl = mojangApiUrl // i dont like this but i cant think of any other way atm :(
endpoint := "users/profiles/minecraft/" + username
url := mojangApiUrl + "/users/profiles/minecraft/" + username

response, err := get[UsernameToUuidResponse](c, ctx, endpoint, http.Header{})
c.baseUrl = oldUrl
return response, err
return do[UsernameToUuidResponse](c, ctx, http.MethodGet, url, http.Header{}, nil)
}

func (c *Client) UuidToProfile(ctx context.Context, uuid string) (*UuidToProfileResponse, error) {
oldUrl := c.baseUrl
c.baseUrl = sessionserverUrl // i dont like this but i cant think of any other way atm :(
endpoint := "session/minecraft/profile/" + uuid
url := sessionserverUrl + "/session/minecraft/profile/" + uuid

response, err := get[UuidToProfileResponse](c, ctx, endpoint, http.Header{})
c.baseUrl = oldUrl
return response, err
return do[UuidToProfileResponse](c, ctx, http.MethodGet, url, http.Header{}, nil)
}
Loading

0 comments on commit dc589d1

Please sign in to comment.