mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Add an app exit banner message
This commit is contained in:
233
support/github.go
Normal file
233
support/github.go
Normal file
@@ -0,0 +1,233 @@
|
||||
package support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
ghb "github.com/google/go-github/v32/github"
|
||||
"github.com/shurcooL/githubv4"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var sponsorQuery struct {
|
||||
User struct {
|
||||
SponsorshipsAsSponsor struct {
|
||||
Nodes []struct {
|
||||
Sponsorable struct {
|
||||
SponsorsListing struct {
|
||||
Slug string
|
||||
}
|
||||
}
|
||||
}
|
||||
} `graphql:"sponsorshipsAsSponsor(first: 10)"`
|
||||
} `graphql:"user(login: $loginName)"`
|
||||
}
|
||||
|
||||
// GitHubUser represents a GitHub user account as defined by a GitHub API access key
|
||||
// This is used to determine whether or not the WTF user is a sponsor (via GitHub sponsors)
|
||||
// and/or a contributor to WTF
|
||||
type GitHubUser struct {
|
||||
apiKey string
|
||||
|
||||
loginName string
|
||||
|
||||
clientV3 *ghb.Client
|
||||
clientV4 *githubv4.Client
|
||||
|
||||
IsContributor bool
|
||||
IsSponsor bool
|
||||
}
|
||||
|
||||
// NewGitHubUser creates and returns an instance of GitHub user with the boolean fields
|
||||
// populated
|
||||
func NewGitHubUser(githubAPIKey string) *GitHubUser {
|
||||
ghUser := GitHubUser{
|
||||
apiKey: githubAPIKey,
|
||||
|
||||
clientV3: nil,
|
||||
clientV4: nil,
|
||||
|
||||
loginName: "",
|
||||
|
||||
IsContributor: false,
|
||||
IsSponsor: false,
|
||||
}
|
||||
|
||||
if ghUser.hasAPIKey() {
|
||||
// Use the v3 API to get the contributors because this doesn't seem to be supported by the v4 API yet
|
||||
clientV3, _ := ghUser.authenticateV3()
|
||||
ghUser.clientV3 = clientV3
|
||||
|
||||
// Use the v4 API to get sponsors because this doesn't seem to be supported in v3
|
||||
clientV4, _ := ghUser.authenticateV4()
|
||||
ghUser.clientV4 = clientV4
|
||||
}
|
||||
|
||||
return &ghUser
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
|
||||
// Load loads the user's data from GitHub
|
||||
func (ghUser *GitHubUser) Load() error {
|
||||
err := ghUser.verifyGitHubClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ghUser.loadGitHubData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (ghUser *GitHubUser) authenticateV3() (*ghb.Client, error) {
|
||||
src := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: ghUser.apiKey},
|
||||
)
|
||||
|
||||
oauthClient := oauth2.NewClient(context.Background(), src)
|
||||
client := ghb.NewClient(oauthClient)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) authenticateV4() (*githubv4.Client, error) {
|
||||
src := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: ghUser.apiKey},
|
||||
)
|
||||
|
||||
oauthClient := oauth2.NewClient(context.Background(), src)
|
||||
client := githubv4.NewClient(oauthClient)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// hasAPIKey returns TRUE if the user has put a GitHub API key into their
|
||||
// configuration and we've managed to find and read it
|
||||
func (ghUser *GitHubUser) hasAPIKey() bool {
|
||||
return ghUser.apiKey != ""
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) loadGitHubData() error {
|
||||
var err error
|
||||
|
||||
login, err := ghUser.loadLoginName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ghUser.loginName = login
|
||||
|
||||
var isContrib, isSponsor bool
|
||||
|
||||
ctx := context.Background()
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
g.Go(func() error {
|
||||
isContrib, err = ghUser.loadContributorStatus(ctx)
|
||||
return err
|
||||
})
|
||||
|
||||
g.Go(func() error {
|
||||
isSponsor, err = ghUser.loadSponsorStatus(ctx)
|
||||
return err
|
||||
})
|
||||
|
||||
err = g.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ghUser.IsContributor = isContrib
|
||||
ghUser.IsSponsor = isSponsor
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadLoginName figures out the GitHub user's login name from their API key
|
||||
func (ghUser *GitHubUser) loadLoginName() (string, error) {
|
||||
user, _, err := ghUser.clientV3.Users.Get(context.Background(), "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
login := user.GetLogin()
|
||||
|
||||
return login, nil
|
||||
}
|
||||
|
||||
// loadContributorStatus figures out if this GitHub account has contributed to WTF
|
||||
func (ghUser *GitHubUser) loadContributorStatus(ctx context.Context) (bool, error) {
|
||||
page := 1
|
||||
isContributor := false
|
||||
|
||||
for {
|
||||
opts := &ghb.ListContributorsOptions{
|
||||
ListOptions: ghb.ListOptions{
|
||||
Page: page,
|
||||
PerPage: 100,
|
||||
},
|
||||
}
|
||||
|
||||
contributors, resp, err := ghUser.clientV3.Repositories.ListContributors(ctx, "wtfutil", "wtf", opts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK || len(contributors) < 1 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, contrib := range contributors {
|
||||
if contrib.GetLogin() == ghUser.loginName {
|
||||
isContributor = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
page++
|
||||
}
|
||||
|
||||
return isContributor, nil
|
||||
}
|
||||
|
||||
// loadSponsorStatus figures out if this GitHub account has sponsored WTF
|
||||
func (ghUser *GitHubUser) loadSponsorStatus(ctx context.Context) (bool, error) {
|
||||
vars := map[string]interface{}{
|
||||
"loginName": githubv4.String(ghUser.loginName),
|
||||
}
|
||||
|
||||
err := ghUser.clientV4.Query(ctx, &sponsorQuery, vars)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
isSponsor := false
|
||||
|
||||
for _, spon := range sponsorQuery.User.SponsorshipsAsSponsor.Nodes {
|
||||
if spon.Sponsorable.SponsorsListing.Slug == "sponsors-senorprogrammer" {
|
||||
isSponsor = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isSponsor, nil
|
||||
}
|
||||
|
||||
func (ghUser *GitHubUser) verifyGitHubClients() error {
|
||||
if ghUser.clientV3 == nil {
|
||||
return errors.New("github client v3 failed to load")
|
||||
}
|
||||
|
||||
if ghUser.clientV4 == nil {
|
||||
return errors.New("github client v4 failed to load")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user