diff --git a/butler/butler.go b/butler/butler.go index 21f2adf..021016e 100644 --- a/butler/butler.go +++ b/butler/butler.go @@ -5,12 +5,12 @@ import ( "net/http" "os" "os/signal" + "strconv" "strings" "syscall" + "time" "github.com/disgoorg/disgo" - "github.com/disgoorg/disgo-butler/db" - "github.com/disgoorg/disgo-butler/mod_mail" "github.com/disgoorg/disgo/bot" "github.com/disgoorg/disgo/cache" "github.com/disgoorg/disgo/discord" @@ -28,6 +28,9 @@ import ( "github.com/hhhapz/doc" "github.com/hhhapz/doc/godocs" gopiston "github.com/milindmadhukar/go-piston" + + "github.com/disgoorg/disgo-butler/db" + "github.com/disgoorg/disgo-butler/mod_mail" ) func New(logger log.Logger, version string, config Config) *Butler { @@ -148,6 +151,10 @@ func (b *Butler) StartAndBlock() { b.Logger.Errorf("Failed to start http server: %s", err) } + contributorCtx, contributorCancel := context.WithCancel(context.Background()) + defer contributorCancel() + go b.RefreshContributorRoles(contributorCtx) + defer func() { b.Logger.Info("Shutting down...") b.Client.Close(context.TODO()) @@ -173,3 +180,68 @@ func (b *Butler) OnReady(_ *events.Ready) { b.Logger.Errorf("Failed to set presence: %s", err) } } + +func (b *Butler) RefreshContributorRoles(ctx context.Context) { + for { + select { + case <-time.After(time.Hour): + b.Logger.Info("Refreshing contributor roles...") + if err := b.UpdateContributorRoles(); err != nil { + b.Logger.Errorf("Failed to update contributor roles: %s", err) + } + case <-ctx.Done(): + return + } + } +} + +func (b *Butler) UpdateContributorRoles() error { + contributors, err := b.DB.GetAllContributors() + if err != nil { + return err + } + + contributorRepos := map[string][]*github.Contributor{} + for _, repo := range b.Config.ContributorRepos { + values := strings.SplitN(repo, "/", 2) + githubContributors, _, err := b.GitHubClient.Repositories.ListContributors(context.TODO(), values[0], values[1], nil) + if err != nil { + return err + } + contributorRepos[repo] = githubContributors + } + + for _, contributor := range contributors { + metadata, err := b.GetContributorMetadata(contributor.Username, contributorRepos) + if err != nil { + b.Logger.Errorf("Failed to get contributor metadata for %s: %s", contributor.Username, err) + continue + } + + session := newSession(contributor) + if _, err = b.OAuth2.UpdateApplicationRoleConnection(session, b.Client.ApplicationID(), discord.ApplicationRoleConnectionUpdate{ + Metadata: &metadata, + }); err != nil { + b.Logger.Errorf("Failed to update contributor roles: %s", err) + } + } + + return nil +} + +func (b *Butler) GetContributorMetadata(username string, contributorRepos map[string][]*github.Contributor) (map[string]string, error) { + metadata := make(map[string]string) + for repo, contributors := range contributorRepos { + for _, contributor := range contributors { + if contributor.GetLogin() == username { + contributions := 0 + if contributor.Contributions != nil { + contributions = *contributor.Contributions + } + metadata[strings.ReplaceAll(repo, "/", "_")+"_contributions"] = strconv.Itoa(contributions) + break + } + } + } + return metadata, nil +} diff --git a/butler/session.go b/butler/session.go new file mode 100644 index 0000000..e3852ae --- /dev/null +++ b/butler/session.go @@ -0,0 +1,54 @@ +package butler + +import ( + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/oauth2" + + "github.com/disgoorg/disgo-butler/db" +) + +var _ oauth2.Session = (*Session)(nil) + +func newSession(contributor db.Contributor) Session { + return Session{ + accessToken: contributor.AccessToken, + refreshToken: contributor.RefreshToken, + scopes: contributor.Scopes, + tokenType: discord.TokenType(contributor.TokenType), + expiration: contributor.Expiration, + } +} + +type Session struct { + accessToken string + refreshToken string + scopes []discord.OAuth2Scope + tokenType discord.TokenType + expiration time.Time +} + +func (s Session) AccessToken() string { + return s.accessToken +} + +func (s Session) RefreshToken() string { + return s.refreshToken +} + +func (s Session) Scopes() []discord.OAuth2Scope { + return s.scopes +} + +func (s Session) TokenType() discord.TokenType { + return s.tokenType +} + +func (s Session) Expiration() time.Time { + return s.expiration +} + +func (s Session) Webhook() *discord.IncomingWebhook { + return nil +} diff --git a/cmd/main.go b/cmd/main.go index f983a80..606de03 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -3,14 +3,15 @@ package main import ( "flag" - "github.com/disgoorg/disgo-butler/butler" - "github.com/disgoorg/disgo-butler/commands" - "github.com/disgoorg/disgo-butler/components" - "github.com/disgoorg/disgo-butler/routes" "github.com/disgoorg/disgo/handler" "github.com/disgoorg/log" "github.com/disgoorg/snowflake/v2" "github.com/go-chi/chi/v5" + + "github.com/disgoorg/disgo-butler/butler" + "github.com/disgoorg/disgo-butler/commands" + "github.com/disgoorg/disgo-butler/components" + "github.com/disgoorg/disgo-butler/routes" ) const version = "development" @@ -49,47 +50,47 @@ func main() { cr := handler.New() cr.Route("/config", func(cr handler.Router) { cr.Route("/aliases", func(cr handler.Router) { - cr.HandleCommand("/add", commands.HandleAliasesAdd(b)) - cr.HandleCommand("/remove", commands.HandleAliasesRemove(b)) - cr.HandleCommand("/list", commands.HandleAliasesList(b)) + cr.Command("/add", commands.HandleAliasesAdd(b)) + cr.Command("/remove", commands.HandleAliasesRemove(b)) + cr.Command("/list", commands.HandleAliasesList(b)) }) cr.Route("/releases", func(cr handler.Router) { - cr.HandleCommand("/add", commands.HandleReleasesAdd(b)) - cr.HandleCommand("/remove", commands.HandleReleasesRemove(b)) - cr.HandleCommand("/list", commands.HandleReleasesList(b)) + cr.Command("/add", commands.HandleReleasesAdd(b)) + cr.Command("/remove", commands.HandleReleasesRemove(b)) + cr.Command("/list", commands.HandleReleasesList(b)) }) cr.Route("/contributor-repos", func(cr handler.Router) { - cr.HandleCommand("/add", commands.HandleContributorReposAdd(b)) - cr.HandleCommand("/remove", commands.HandleContributorReposRemove(b)) - cr.HandleCommand("/list", commands.HandleContributorReposList(b)) + cr.Command("/add", commands.HandleContributorReposAdd(b)) + cr.Command("/remove", commands.HandleContributorReposRemove(b)) + cr.Command("/list", commands.HandleContributorReposList(b)) }) }) cr.Route("/docs", func(cr handler.Router) { - cr.HandleCommand("/", commands.HandleDocs(b)) - cr.HandleAutocomplete("/", commands.HandleDocsAutocomplete(b)) + cr.Command("/", commands.HandleDocs(b)) + cr.Autocomplete("/", commands.HandleDocsAutocomplete(b)) }) - cr.HandleComponent("docs_action", components.HandleDocsAction(b)) - cr.HandleComponent("eval/rerun/{message_id}", components.HandleEvalRerunAction(b)) - cr.HandleComponent("eval/delete", components.HandleEvalDeleteAction) - cr.HandleCommand("/eval", commands.HandleEval(b)) - cr.HandleCommand("/info", commands.HandleInfo(b)) - cr.HandleCommand("/ping", commands.HandlePing) + cr.Component("docs_action", components.HandleDocsAction(b)) + cr.Component("eval/rerun/{message_id}", components.HandleEvalRerunAction(b)) + cr.Component("eval/delete", components.HandleEvalDeleteAction) + cr.Command("/eval", commands.HandleEval(b)) + cr.Command("/info", commands.HandleInfo(b)) + cr.Command("/ping", commands.HandlePing) cr.Route("/tag", func(cr handler.Router) { - cr.HandleCommand("/", commands.HandleTag(b)) - cr.HandleAutocomplete("/", commands.HandleTagListAutoComplete(b, false)) + cr.Command("/", commands.HandleTag(b)) + cr.Autocomplete("/", commands.HandleTagListAutoComplete(b, false)) }) cr.Route("/tags", func(cr handler.Router) { - cr.HandleCommand("/create", commands.HandleCreateTag(b)) - cr.HandleCommand("/edit", commands.HandleEditTag(b)) - cr.HandleCommand("/delete", commands.HandleDeleteTag(b)) - cr.HandleCommand("/info", commands.HandleTagInfo(b)) - cr.HandleCommand("/list", commands.HandleListTags(b)) - cr.HandleAutocomplete("/edit", commands.HandleTagListAutoComplete(b, true)) - cr.HandleAutocomplete("/delete", commands.HandleTagListAutoComplete(b, true)) - cr.HandleAutocomplete("/info", commands.HandleTagListAutoComplete(b, false)) - cr.HandleAutocomplete("/list", commands.HandleTagListAutoComplete(b, false)) + cr.Command("/create", commands.HandleCreateTag(b)) + cr.Command("/edit", commands.HandleEditTag(b)) + cr.Command("/delete", commands.HandleDeleteTag(b)) + cr.Command("/info", commands.HandleTagInfo(b)) + cr.Command("/list", commands.HandleListTags(b)) + cr.Autocomplete("/edit", commands.HandleTagListAutoComplete(b, true)) + cr.Autocomplete("/delete", commands.HandleTagListAutoComplete(b, true)) + cr.Autocomplete("/info", commands.HandleTagListAutoComplete(b, false)) + cr.Autocomplete("/list", commands.HandleTagListAutoComplete(b, false)) }) - cr.HandleCommand("/close-ticket", commands.HandleCloseTicket(b)) + cr.Command("/close-ticket", commands.HandleCloseTicket(b)) b.SetupBot(cr) b.SetupDB(*shouldSyncDBTables) b.RegisterLinkedRoles() diff --git a/db/contributors.go b/db/contributors.go new file mode 100644 index 0000000..b649e2c --- /dev/null +++ b/db/contributors.go @@ -0,0 +1,53 @@ +package db + +import ( + "context" + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/oauth2" +) + +type Contributor struct { + Username string `bun:"username,pk"` + AccessToken string `bun:"access_token,notnull"` + RefreshToken string `bun:"refresh_token,notnull"` + Scopes []discord.OAuth2Scope `bun:"scopes,notnull"` + TokenType discord.TokenType `bun:"token_type,notnull"` + Expiration time.Time `bun:"expiration,notnull"` +} + +type ContributorsDB interface { + GetAllContributors() ([]Contributor, error) + AddContributor(username string, session oauth2.Session) error + DeleteContributor(username string) error +} + +func (s *sqlDB) GetAllContributors() (contributors []Contributor, err error) { + err = s.db.NewSelect(). + Model(&contributors). + Scan(context.TODO()) + return +} + +func (s *sqlDB) AddContributor(username string, session oauth2.Session) (err error) { + _, err = s.db.NewInsert(). + Model(&Contributor{ + Username: username, + AccessToken: session.AccessToken(), + RefreshToken: session.RefreshToken(), + Scopes: session.Scopes(), + TokenType: session.TokenType(), + Expiration: session.Expiration(), + }). + Exec(context.TODO()) + return +} + +func (s *sqlDB) DeleteContributor(username string) (err error) { + _, err = s.db.NewDelete(). + Model(&Contributor{}). + Where("username = ?", username). + Exec(context.TODO()) + return +} diff --git a/db/db.go b/db/db.go index e649009..e4ce407 100644 --- a/db/db.go +++ b/db/db.go @@ -34,6 +34,9 @@ func SetupDatabase(shouldSyncDBTables bool, config Config) (DB, error) { if _, err := db.NewCreateTable().Model((*Tag)(nil)).Exec(context.TODO()); err != nil { return nil, err } + if _, err := db.NewCreateTable().Model((*Contributor)(nil)).Exec(context.TODO()); err != nil { + return nil, err + } } return &sqlDB{db: db}, nil @@ -41,6 +44,7 @@ func SetupDatabase(shouldSyncDBTables bool, config Config) (DB, error) { type DB interface { TagsDB + ContributorsDB Close() } diff --git a/go.mod b/go.mod index 8e68113..c82e39f 100644 --- a/go.mod +++ b/go.mod @@ -3,39 +3,39 @@ module github.com/disgoorg/disgo-butler go 1.18 require ( - github.com/disgoorg/disgo v0.14.2-0.20230103162111-29c995c348d1 + github.com/disgoorg/disgo v0.15.1 github.com/disgoorg/json v1.0.0 github.com/disgoorg/log v1.2.0 github.com/disgoorg/paginator v0.0.0-20230104145353-f988d828ede9 github.com/disgoorg/snowflake/v2 v2.0.1 - github.com/go-chi/chi/v5 v5.0.7 + github.com/go-chi/chi/v5 v5.0.8 github.com/google/go-github/v44 v44.1.0 github.com/hhhapz/doc v0.5.1 github.com/lithammer/fuzzysearch v1.1.5 github.com/milindmadhukar/go-piston v0.0.0-20211122120254-64da61081d05 - github.com/uptrace/bun v1.1.8 - github.com/uptrace/bun/dialect/pgdialect v1.1.8 - github.com/uptrace/bun/driver/pgdriver v1.1.8 - github.com/uptrace/bun/extra/bundebug v1.1.8 - golang.org/x/exp v0.0.0-20220914170420-dc92f8653013 + github.com/uptrace/bun v1.1.11 + github.com/uptrace/bun/dialect/pgdialect v1.1.11 + github.com/uptrace/bun/driver/pgdriver v1.1.11 + github.com/uptrace/bun/extra/bundebug v1.1.11 + golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb ) require ( github.com/PuerkitoBio/goquery v1.8.0 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect - golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect - golang.org/x/sys v0.0.0-20220913175220-63ea55921009 // indirect - golang.org/x/text v0.3.7 // indirect - mellium.im/sasl v0.3.0 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + mellium.im/sasl v0.3.1 // indirect ) diff --git a/go.sum b/go.sum index 90ba803..aff6368 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/disgoorg/disgo v0.14.2-0.20230103162111-29c995c348d1 h1:SqpUrD07kf3fFA6OmXCAcmfz7jorxAa+rTKsLtY3zSc= github.com/disgoorg/disgo v0.14.2-0.20230103162111-29c995c348d1/go.mod h1:YiVpXSmyXLRalYQHTHUFWEQvolCNzw0zh6nfug07b/M= +github.com/disgoorg/disgo v0.15.1 h1:EO7tV0r0VnktjubRaYi78APXrOLvIetPhwv+W61HkVY= +github.com/disgoorg/disgo v0.15.1/go.mod h1:j7MCI6foUipYNozxwttr2hcaEQa3gNEbcwgLnyLUf6E= github.com/disgoorg/json v1.0.0 h1:kDhSM661fgIuNoZF3BO5/odaR5NSq80AWb937DH+Pdo= github.com/disgoorg/json v1.0.0/go.mod h1:BHDwdde0rpQFDVsRLKhma6Y7fTbQKub/zdGO5O9NqqA= github.com/disgoorg/log v1.2.0 h1:sqlXnu/ZKAlIlHV9IO+dbMto7/hCQ474vlIdMWk8QKo= @@ -16,8 +18,12 @@ github.com/disgoorg/snowflake/v2 v2.0.1 h1:CuUxGLwggUxEswZOmZ+mZ5i0xSumQdXW9tXW7 github.com/disgoorg/snowflake/v2 v2.0.1/go.mod h1:SPU9c2CNn5DSyb86QcKtdZgix9osEtKrHLW4rMhfLCs= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-github/v44 v44.1.0 h1:shWPaufgdhr+Ad4eo/pZv9ORTxFpsxPEPEuuXAKIQGA= @@ -39,6 +45,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/milindmadhukar/go-piston v0.0.0-20211122120254-64da61081d05 h1:DJtDN26io353OHf60ahLS7ZmwnNmiMEoIL1Z5HT3v8I= github.com/milindmadhukar/go-piston v0.0.0-20211122120254-64da61081d05/go.mod h1:UGaEMhOv9qK6z4E663UiqUB1M7J+aXDJV716oclA8Dg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -52,23 +60,37 @@ github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYm github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= github.com/uptrace/bun v1.1.8 h1:slxuaP4LYWFbPRUmTtQhfJN+6eX/6ar2HDKYTcI50SA= github.com/uptrace/bun v1.1.8/go.mod h1:iT89ESdV3uMupD9ixt6Khidht+BK0STabK/LeZE+B84= +github.com/uptrace/bun v1.1.11 h1:PVT+DHdLX13tIJaBoT0tkjh1TOWOybW/pz3TKiOB9lo= +github.com/uptrace/bun v1.1.11/go.mod h1:ysoB7l3gioKLBaZH9wKuJAoeBiOthb/hTyKdbXKcaxg= github.com/uptrace/bun/dialect/pgdialect v1.1.8 h1:wayJhjYDPGv8tgOBLolbBtSFQ0TihFoo8E1T129UdA8= github.com/uptrace/bun/dialect/pgdialect v1.1.8/go.mod h1:nNbU8PHTjTUM+CRtGmqyBb9zcuRAB8I680/qoFSmBUk= +github.com/uptrace/bun/dialect/pgdialect v1.1.11 h1:z1CLRQiYtTX1Usn2OEF7EtOBYeTFJiNdTgLuXE+AZZs= +github.com/uptrace/bun/dialect/pgdialect v1.1.11/go.mod h1:orzsx6UwNnSaTTELzLqc/XiWrR4k0Smid8Bchdg0mk4= github.com/uptrace/bun/driver/pgdriver v1.1.8 h1:gyL22axRQfjJS2Umq0erzJnp0bLOdUE8/USKZHPQB8o= github.com/uptrace/bun/driver/pgdriver v1.1.8/go.mod h1:4tHK0h7a/UoldBoe9J3GU4tEYjr3mkd62U3Kq3PVk3E= +github.com/uptrace/bun/driver/pgdriver v1.1.11 h1:0oKNY3cBuIs6wHCJP2IpUw5wPoeUa8oIDEvIdei+sDI= +github.com/uptrace/bun/driver/pgdriver v1.1.11/go.mod h1:c5x3/2B63Vw876N1GjWJbqQOE3k68+8abMc428PKG18= github.com/uptrace/bun/extra/bundebug v1.1.8 h1:RrZNOYYFb690k14nCN0t/hokfpsgoppT55/Xk/ijvBA= github.com/uptrace/bun/extra/bundebug v1.1.8/go.mod h1:AXl9cPt1j3Yyu+a681xTlDyWoIBL1iSjTjr2SAU5oUY= +github.com/uptrace/bun/extra/bundebug v1.1.11 h1:XM3hgJZvfchvnDhBqPYGqmPaZE2PIeitOTC0rPeEDUU= +github.com/uptrace/bun/extra/bundebug v1.1.11/go.mod h1:BpEJIYkF9nIt6M5ULgPN3zOIhwt+pHBe8cb8ZuMslKs= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20220914170420-dc92f8653013 h1:ZjglnWxEUdPyXl4o/j4T89SRCI+4X6NW6185PNLEOF4= golang.org/x/exp v0.0.0-20220914170420-dc92f8653013/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -77,10 +99,14 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220913175220-63ea55921009 h1:PuvuRMeLWqsf/ZdT1UUZz0syhioyv1mzuFZsXs4fvhw= golang.org/x/sys v0.0.0-20220913175220-63ea55921009/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -88,3 +114,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= mellium.im/sasl v0.3.0 h1:0qoaTCTo5Py7u/g0cBIQZcMOgG/5LM71nshbXwznBh8= mellium.im/sasl v0.3.0/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= +mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= diff --git a/routes/discord_login.go b/routes/discord_login.go index 318adf1..358e433 100644 --- a/routes/discord_login.go +++ b/routes/discord_login.go @@ -1,15 +1,14 @@ package routes import ( - "context" "embed" "html/template" "net/http" - "strconv" "strings" "github.com/disgoorg/disgo/discord" "github.com/disgoorg/json" + "github.com/google/go-github/v44/github" "github.com/disgoorg/disgo-butler/butler" ) @@ -63,26 +62,26 @@ func HandleGithub(b *butler.Butler) http.HandlerFunc { return } - metadata := make(map[string]string) + if err = b.DB.AddContributor(conn.Name, session); err != nil { + httpError(w, err) + return + } + + contributorRepos := map[string][]*github.Contributor{} for _, repo := range b.Config.ContributorRepos { values := strings.SplitN(repo, "/", 2) - contributors, _, err := b.GitHubClient.Repositories.ListContributors(context.TODO(), values[0], values[1], nil) + githubContributors, _, err := b.GitHubClient.Repositories.ListContributors(r.Context(), values[0], values[1], nil) if err != nil { httpError(w, err) return } - for _, contributor := range contributors { - if contributor.GetLogin() == conn.Name { - // need at least 10 contributions - contributions := 0 - if contributor.Contributions != nil { - contributions = *contributor.Contributions - } - metadata[strings.ReplaceAll(repo, "/", "_")+"_contributions"] = strconv.Itoa(contributions) - break - } - } + contributorRepos[repo] = githubContributors + } + metadata, err := b.GetContributorMetadata(conn.Name, contributorRepos) + if err != nil { + httpError(w, err) + return } if _, err = b.OAuth2.UpdateApplicationRoleConnection(session, b.Client.ApplicationID(), discord.ApplicationRoleConnectionUpdate{