sponsors.go - query whether a GitHub user is your sponsor at a given tier (dollar amount)
// LICENSE for this file: MIT | |
// Copyright: Alex Ellis, OpenFaaS Ltd 2020 | |
// Do not remove this notice | |
package handlers | |
import ( | |
"context" | |
"encoding/json" | |
"os" | |
"github.com/shurcooL/githubv4" | |
"golang.org/x/oauth2" | |
) | |
const minDollars = 25 | |
type SponsorTier struct { | |
MonthlyPriceInDollars int | |
} | |
// SponsorEntity is the User sponsoring | |
type SponsorEntity struct { | |
// SponsorUser with an annotation that expands the Union for the User type | |
SponsorUser SponsorUser `graphql:"... on User"` | |
} | |
// Sponsorable is the User receiving the sponsorshop | |
type Sponsorable struct { | |
// SponsorUser with an annotation that expands the Union for the User type | |
SponsorUser SponsorUser `graphql:"... on User"` | |
// SponsorOrganization was not strictly required, during debug the SponsorUser | |
// was populated with the org name anyway. | |
SponsorOrganization SponsorUser `graphql:"... on Organization"` | |
} | |
// SponsorUser is a User associated with either side of a | |
// sponsorship | |
type SponsorUser struct { | |
// Login name of the sponsor. | |
Login string | |
} | |
// sponsorships is the query for graphql and it limits | |
// the search to 100, since most people will not be | |
// sponsoring more than a few other developers. | |
type sponsorships struct { | |
Viewer struct { | |
Login string | |
SponsorshipsAsSponsor struct { | |
Nodes []struct { | |
SponsorEntity SponsorEntity | |
Sponsorable Sponsorable | |
Tier SponsorTier | |
} | |
} `graphql:"sponsorshipsAsSponsor(first: 100)"` | |
} | |
} | |
// IsSponsoring returns true if the login for the associated | |
// accessToken has an active sponsorship for the target login of | |
// the hard-coded dollar amount. | |
// The accessToken requires the whole "user" scope to read the | |
// dollar amount. | |
func IsSponsoring(login string, targets []string, accessToken string) (bool, error) { | |
// it's not possible to sponsor oneself | |
for _, target := range targets { | |
if target == login { | |
return true, nil | |
} | |
} | |
src := oauth2.StaticTokenSource( | |
&oauth2.Token{AccessToken: accessToken}, | |
) | |
httpClient := oauth2.NewClient(context.Background(), src) | |
client := githubv4.NewClient(httpClient) | |
var q sponsorships | |
ctx := context.Background() | |
err := client.Query(ctx, &q, map[string]interface{}{}) | |
if err != nil { | |
return false, err | |
} | |
// log.Printf("Checking %s, for: %v", login, targets) | |
// printJSON(q.Viewer.SponsorshipsAsSponsor.Nodes) | |
var users []SponsorUser | |
for _, node := range q.Viewer.SponsorshipsAsSponsor.Nodes { | |
sponsor := node.SponsorEntity.SponsorUser | |
sponsored := node.Sponsorable.SponsorUser.Login | |
for _, target := range targets { | |
if sponsored == target && | |
node.Tier.MonthlyPriceInDollars >= minDollars { | |
users = append(users, sponsor) | |
} | |
} | |
} | |
for _, s := range users { | |
if s.Login == login { | |
return true, nil | |
} | |
} | |
return false, nil | |
} | |
// printJSON is from the github.com/shurcooL/githubv4 library | |
// and prints the response for debugging. | |
func printJSON(v interface{}) { | |
w := json.NewEncoder(os.Stdout) | |
w.SetIndent("", "\t") | |
err := w.Encode(v) | |
if err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment