Skip to content

Commit

Permalink
feat: add Polar.sh provider (#66)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <github@antfu.me>
  • Loading branch information
Julien-R44 and antfu committed May 6, 2024
1 parent ced97c0 commit 40eb415
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Supports:
- [**Patreon**](https://www.patreon.com/)
- [**OpenCollective**](https://opencollective.com/)
- [**Afdian**](https://afdian.net/)
- [**Polar**](https://polar.sh/)

## Usage

Expand Down Expand Up @@ -43,6 +44,10 @@ SPONSORKIT_OPENCOLLECTIVE_TYPE=
SPONSORKIT_AFDIAN_USER_ID=
; Create token at https://afdian.net/dashboard/dev
SPONSORKIT_AFDIAN_TOKEN=

; Polar provider.
; Get your token at https://polar.sh/settings
SPONSORKIT_POLAR_TOKEN=
```

> Only one provider is required to be configured.
Expand Down Expand Up @@ -77,6 +82,9 @@ export default defineConfig({
afdian: {
// ...
},
polar: {
// ...
},

// Rendering configs
width: 800,
Expand Down
3 changes: 3 additions & 0 deletions src/configs/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export function loadEnv(): Partial<SponsorkitConfig> {
token: process.env.SPONSORKIT_AFDIAN_TOKEN || process.env.AFDIAN_TOKEN,
exechangeRate: Number.parseFloat(process.env.SPONSORKIT_AFDIAN_EXECHANGERATE || process.env.AFDIAN_EXECHANGERATE || '0') || undefined,
},
polar: {
token: process.env.SPONSORKIT_POLAR_TOKEN || process.env.POLAR_TOKEN,
},
outputDir: process.env.SPONSORKIT_DIR,
}

Expand Down
5 changes: 5 additions & 0 deletions src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { GitHubProvider } from './github'
import { PatreonProvider } from './patreon'
import { OpenCollectiveProvider } from './opencollective'
import { AfdianProvider } from './afdian'
import { PolarProvider } from './polar'

export * from './github'

Expand All @@ -11,6 +12,7 @@ export const ProvidersMap = {
patreon: PatreonProvider,
opencollective: OpenCollectiveProvider,
afdian: AfdianProvider,
polar: PolarProvider,
}

export function guessProviders(config: SponsorkitConfig) {
Expand All @@ -27,6 +29,9 @@ export function guessProviders(config: SponsorkitConfig) {
if (config.afdian && config.afdian.userId && config.afdian.token)
items.push('afdian')

if (config.polar && config.polar.token)
items.push('polar')

// fallback
if (!items.length)
items.push('github')
Expand Down
58 changes: 58 additions & 0 deletions src/providers/polar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ofetch } from 'ofetch'
import type { Provider, Sponsorship } from '../types'

export const PolarProvider: Provider = {
name: 'polar',
fetchSponsors(config) {
return fetchPolarSponsors(config.polar?.token || config.token!)
},
}

export async function fetchPolarSponsors(token: string): Promise<Sponsorship[]> {
if (!token)
throw new Error('Polar token is required')

const apiFetch = ofetch.create({
baseURL: 'https://api.polar.sh/api/v1',
headers: { Authorization: `Bearer ${token}` },
})

/**
* First fetch the list of all subscriptions. This is a paginated
* endpoint so loop through all the pages
*/
let page = 1
let pages = 1
const subscriptions = []
do {
const subs = await apiFetch('/subscriptions/subscriptions/search', { params: { page } })
subscriptions.push(...subs.items)

pages = subs.pagination.max_page
page += 1
} while (page <= pages)

return subscriptions
/**
* - People can subscribe for free on Polar : the price is null in this case
*/
.filter(sub => !!sub.price)
.map((sub) => {
const isActive = sub.status === 'active'

return {
sponsor: {
name: sub.user.public_name,
avatarUrl: sub.user.avatar_url,
login: sub.user.github_username,
type: sub.subscription_tier.type === 'individual' ? 'User' : 'Organization',
},
isOneTime: false,
provider: 'polar',
privacyLevel: 'PUBLIC',
createdAt: new Date(sub.created_at).toISOString(),
tierName: isActive ? sub.subscription_tier.name : undefined,
monthlyDollars: isActive ? sub.sub.price.price_amount / 100 : -1,
}
})
}
14 changes: 13 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export interface Sponsorship {

export type OutputFormat = 'svg' | 'png' | 'json'

export type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian'
export type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar'

export interface ProvidersConfig {
github?: {
Expand Down Expand Up @@ -155,6 +155,18 @@ export interface ProvidersConfig {
*/
exechangeRate?: number
}

polar?: {
/**
* Polar token that have access to your sponsorships.
*
* Will read from `SPONSORKIT_POLAR_TOKEN` environment variable if not set.
*
* @see https://polar.sh/settings
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string
}
}

export interface SponsorkitRenderOptions {
Expand Down

0 comments on commit 40eb415

Please sign in to comment.