Skip to content

Commit

Permalink
add start.gg provider
Browse files Browse the repository at this point in the history
  • Loading branch information
pilcrowonpaper committed Sep 16, 2024
1 parent 6ab0262 commit afd45a5
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Arctic does not strictly follow semantic versioning. While we aim to only introd
- Shikimori
- Slack
- Spotify
- Start.gg
- Strava
- Tiltify
- Tumblr
Expand Down
1 change: 1 addition & 0 deletions docs/malta.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
["Shikimori", "/providers/shikimori"],
["Slack", "/providers/slack"],
["Spotify", "/providers/spotify"],
["Start.gg", "/providers/startgg"],
["Strava", "/providers/strava"],
["Tiltify", "/providers/tiltify"],
["Tumblr", "/providers/tumblr"],
Expand Down
93 changes: 93 additions & 0 deletions docs/pages/providers/startgg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "Start.gg"
---

# Start.gg

OAuth 2.0 provider for Start.gg.

Also see the [OAuth 2.0](/guides/oauth2) guide.

## Initialization

```ts
import { StartGG } from "arctic";

const startgg = new StartGG(clientId, clientSecret, redirectURI);
```

## Create authorization URL

```ts
import { generateState } from "arctic";

const state = generateState();
const scopes = ["user.identity", "user.email"];
const url = startgg.createAuthorizationURL(state, scopes);
```

## Validate authorization code

Start.gg requires a list of scopes in addition to the authorization code. `validateAuthorizationCode()` will either return an [`OAuth2Tokens`](/reference/main/OAuth2Tokens), or throw one of [`OAuth2RequestError`](/reference/main/OAuth2RequestError), [`ArcticFetchError`](/reference/main/ArcticFetchError), or a standard `Error` (parse errors). Start.gg returns an access token, the access token expiration, and a refresh token.

```ts
import { OAuth2RequestError, ArcticFetchError } from "arctic";

try {
const tokens = await startgg.validateAuthorizationCode(code, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}
```

## Refresh access tokens

Use `refreshAccessToken()` to get a new access token using a refresh token. Start.gg returns the same values as during the authorization code validation. This method also returns `OAuth2Tokens` and throws the same errors as `validateAuthorizationCode()`

```ts
import { OAuth2RequestError, ArcticFetchError } from "arctic";

try {
const tokens = await startgg.refreshAccessToken(accessToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}
```

## Get user profile

Add the `user.identity` scope and optionally the `user.email` to get the user email. See the [Start.gg Schema](https://developer.start.gg/reference/user.doc).

```ts
const response = await fetch("https://api.start.gg/gql/alpha", {
method: "POST",
body: `{"query": "{ currentUser {id slug email player { gamerTag } } }" }`,
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${accessToken}`
}
});
const result = await response.json();
```
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export { Salesforce } from "./providers/salesforce.js";
export { Shikimori } from "./providers/shikimori.js";
export { Slack } from "./providers/slack.js";
export { Spotify } from "./providers/spotify.js";
export { StartGG } from "./providers/startgg.js";
export { Strava } from "./providers/strava.js";
export { Tiltify } from "./providers/tiltify.js";
export { Tumblr } from "./providers/tumblr.js";
Expand Down
55 changes: 55 additions & 0 deletions src/providers/startgg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { createOAuth2Request, sendTokenRequest } from "../request.js";

import type { OAuth2Tokens } from "../oauth2.js";

const authorizationEndpoint = "https://start.gg/oauth/authoriz";
const tokenEndpoint = "https://api.start.gg/oauth/access_token";
const refreshEndpoint = "https://api.start.gg/oauth/refresh";

export class StartGG {
private clientId: string;
private clientSecret: string;
private redirectURI: string;

constructor(clientId: string, clientSecret: string, redirectURI: string) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.redirectURI = redirectURI;
}

public createAuthorizationURL(state: string, scopes: string[]): URL {
const url = new URL(authorizationEndpoint);
url.searchParams.set("response_type", "code");
url.searchParams.set("client_id", this.clientId);
url.searchParams.set("state", state);
url.searchParams.set("scope", scopes.join(" "));
url.searchParams.set("redirect_uri", this.redirectURI);
return url;
}

public async validateAuthorizationCode(code: string, scopes: string[]): Promise<OAuth2Tokens> {
const body = new URLSearchParams();
body.set("grant_type", "authorization_code");
body.set("code", code);
body.set("redirect_uri", this.redirectURI);
body.set("client_id", this.clientId);
body.set("client_secret", this.clientSecret);
body.set("scope", scopes.join(" "));
const request = createOAuth2Request(tokenEndpoint, body);
const tokens = await sendTokenRequest(request);
return tokens;
}

public async refreshAccessToken(refreshToken: string, scopes: string[]): Promise<OAuth2Tokens> {
const body = new URLSearchParams();
body.set("grant_type", "refresh_token");
body.set("refresh_token", refreshToken);
body.set("redirect_uri", this.redirectURI);
body.set("client_id", this.clientId);
body.set("client_secret", this.clientSecret);
body.set("scope", scopes.join(" "));
const request = createOAuth2Request(refreshEndpoint, body);
const tokens = await sendTokenRequest(request);
return tokens;
}
}

0 comments on commit afd45a5

Please sign in to comment.