add patches
This commit is contained in:
parent
301379574a
commit
32b87975d0
9 changed files with 271 additions and 125 deletions
|
@ -4,8 +4,9 @@ subscribe-bot
|
||||||
Subscribes to OSU map updates and stores versions for later review.
|
Subscribes to OSU map updates and stores versions for later review.
|
||||||
|
|
||||||
Please don't run a separate bot, the official one is `subscribe-bot#8789`. If
|
Please don't run a separate bot, the official one is `subscribe-bot#8789`. If
|
||||||
you want to contribute or test the bot, then here are instructions on how to
|
you want to contribute or test the bot, instructions on how to run it are below.
|
||||||
run it:
|
|
||||||
|
Join the [Discord][2]
|
||||||
|
|
||||||
How to run
|
How to run
|
||||||
----------
|
----------
|
||||||
|
@ -37,3 +38,4 @@ License
|
||||||
[GPL3][1]
|
[GPL3][1]
|
||||||
|
|
||||||
[1]: https://www.gnu.org/licenses/gpl-3.0.en.html
|
[1]: https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
[2]: https://discord.gg/eqjVG2H
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -6,6 +6,7 @@ require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
|
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
|
||||||
github.com/bwmarrin/discordgo v0.22.0
|
github.com/bwmarrin/discordgo v0.22.0
|
||||||
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/foolin/goview v0.3.0
|
github.com/foolin/goview v0.3.0
|
||||||
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e
|
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e
|
||||||
github.com/gin-gonic/contrib v0.0.0-20201005132743-ca038bbf2944
|
github.com/gin-gonic/contrib v0.0.0-20201005132743-ca038bbf2944
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -15,6 +15,8 @@ github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CL
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||||
|
|
67
web/auth.go
Normal file
67
web/auth.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (web *Web) logout(c *gin.Context) {
|
||||||
|
session := sessions.Default(c)
|
||||||
|
session.Delete("access_token")
|
||||||
|
session.Save()
|
||||||
|
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (web *Web) login(c *gin.Context) {
|
||||||
|
url := url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "osu.ppy.sh",
|
||||||
|
Path: "/oauth/authorize",
|
||||||
|
}
|
||||||
|
q := url.Query()
|
||||||
|
q.Set("client_id", web.config.Oauth.ClientId)
|
||||||
|
q.Set("redirect_uri", web.config.Web.ServedAt+"/login/callback")
|
||||||
|
q.Set("response_type", "code")
|
||||||
|
q.Set("scope", "identify public")
|
||||||
|
q.Set("state", "urmom")
|
||||||
|
url.RawQuery = q.Encode()
|
||||||
|
fmt.Println("redirecting to", url.String())
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, url.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (web *Web) loginCallback(c *gin.Context) {
|
||||||
|
receivedCode := c.Query("code")
|
||||||
|
|
||||||
|
bodyQuery := url.Values{}
|
||||||
|
bodyQuery.Set("client_id", web.config.Oauth.ClientId)
|
||||||
|
bodyQuery.Set("client_secret", web.config.Oauth.ClientSecret)
|
||||||
|
bodyQuery.Set("code", receivedCode)
|
||||||
|
bodyQuery.Set("grant_type", "authorization_code")
|
||||||
|
bodyQuery.Set("redirect_uri", web.config.Web.ServedAt+"/login/callback")
|
||||||
|
body := strings.NewReader(bodyQuery.Encode())
|
||||||
|
resp, _ := web.hc.Post("https://osu.ppy.sh/oauth/token", "application/x-www-form-urlencoded", body)
|
||||||
|
respBody, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
type OsuToken struct {
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
}
|
||||||
|
var token OsuToken
|
||||||
|
_ = json.Unmarshal(respBody, &token)
|
||||||
|
fmt.Println("TOKEN", token)
|
||||||
|
|
||||||
|
session := sessions.Default(c)
|
||||||
|
session.Set("access_token", token.AccessToken)
|
||||||
|
session.Save()
|
||||||
|
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||||
|
}
|
73
web/repo.go
Normal file
73
web/repo.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (web *Web) mapVersions(c *gin.Context) {
|
||||||
|
userId := c.Param("userId")
|
||||||
|
mapId := c.Param("mapId")
|
||||||
|
|
||||||
|
repoDir := path.Join(web.config.Repos, userId, mapId)
|
||||||
|
repo, _ := git.PlainOpen(repoDir)
|
||||||
|
|
||||||
|
type Revision struct {
|
||||||
|
Date time.Time
|
||||||
|
HumanDate string
|
||||||
|
Summary string
|
||||||
|
Hash string
|
||||||
|
HasParent bool
|
||||||
|
}
|
||||||
|
|
||||||
|
versions := make([]Revision, 0)
|
||||||
|
logIter, _ := repo.Log(&git.LogOptions{})
|
||||||
|
for {
|
||||||
|
commit, err := logIter.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, _ := commit.Stats()
|
||||||
|
_, err = commit.Parent(0)
|
||||||
|
hasParent := !errors.Is(err, object.ErrParentNotFound)
|
||||||
|
|
||||||
|
versions = append(versions, Revision{
|
||||||
|
Date: commit.Author.When,
|
||||||
|
HumanDate: humanize.Time(commit.Author.When),
|
||||||
|
Summary: stats.String(),
|
||||||
|
Hash: commit.Hash.String(),
|
||||||
|
HasParent: hasParent,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "map-version.html", gin.H{
|
||||||
|
"LoggedIn": isLoggedIn(c),
|
||||||
|
"Versions": versions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (web *Web) mapPatch(c *gin.Context) {
|
||||||
|
userId := c.Param("userId")
|
||||||
|
mapId := c.Param("mapId")
|
||||||
|
hash := c.Param("hash")
|
||||||
|
|
||||||
|
repoDir := path.Join(web.config.Repos, userId, mapId)
|
||||||
|
repo, _ := git.PlainOpen(repoDir)
|
||||||
|
|
||||||
|
hashObj := plumbing.NewHash(hash)
|
||||||
|
commit, _ := repo.CommitObject(hashObj)
|
||||||
|
parent, _ := commit.Parent(0)
|
||||||
|
patch, _ := commit.Patch(parent)
|
||||||
|
|
||||||
|
c.String(http.StatusOK, "text/plain", patch.String())
|
||||||
|
}
|
|
@ -1,51 +1,27 @@
|
||||||
<!DOCTYPE html>
|
{{ define "content" }}
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>subscribe-bot</title>
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<p>Maps:</p>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/main.css" />
|
<table class="table-auto">
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1 class="title">
|
|
||||||
<a href="/">subscribe-bot</a>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<small>logging in with your osu account does nothing</small>
|
|
||||||
|
|
||||||
<div class="nav-bar">
|
|
||||||
<a href="/">home</a>
|
|
||||||
|
|
||||||
{{ if .LoggedIn }}
|
|
||||||
<a href="/logout">logout</a>
|
|
||||||
{{ else }}
|
|
||||||
<a href="/login">login</a>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Maps:</p>
|
|
||||||
|
|
||||||
<table class="table-auto">
|
|
||||||
<thead>
|
<thead>
|
||||||
<th>Mapper</th>
|
|
||||||
<th>Title</th>
|
|
||||||
<th>Links</th>
|
<th>Links</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Mapper</th>
|
||||||
</thead>
|
</thead>
|
||||||
{{ range .Beatmapsets }}
|
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{{ range .Beatmapsets }}
|
||||||
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://osu.ppy.sh/u/{{ .UserID }}" target="_blank">{{ .Creator }}</a>
|
<a href="https://osu.ppy.sh/s/{{ .ID }}" target="_blank">osu</a>
|
||||||
|
<a href="/map/{{ .UserID }}/{{ .ID }}/versions">versions</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ .Artist }} - {{ .Title }}</td>
|
<td>{{ .Artist }} - {{ .Title }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://osu.ppy.sh/s/{{ .ID }}" target="_blank">osu</a>
|
<a href="https://osu.ppy.sh/u/{{ .UserID }}" target="_blank">{{ .Creator }}</a>
|
||||||
</td>
|
</td>
|
||||||
</tbody>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</table>
|
</tbody>
|
||||||
</div>
|
</table>
|
||||||
</body>
|
|
||||||
</html>
|
{{ end }}
|
||||||
|
|
27
web/templates/map-version.html
Normal file
27
web/templates/map-version.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
|
||||||
|
<small>up to the latest 20 revisions, pagination coming later</small>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Links</th>
|
||||||
|
<th>Summary</th>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{ range .Versions }}
|
||||||
|
<tr>
|
||||||
|
<td><span title="{{ .Date }}">{{ .HumanDate }}</span></td>
|
||||||
|
<td>
|
||||||
|
{{ if .HasParent }}
|
||||||
|
<a href="patch/{{ .Hash }}">patch</a>
|
||||||
|
{{ end }}
|
||||||
|
</td>
|
||||||
|
<td><pre>{{ .Summary }}</pre></td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{{ end }}
|
32
web/templates/master.html
Normal file
32
web/templates/master.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>subscribe-bot</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/static/main.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title">
|
||||||
|
<a href="/">subscribe-bot</a>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<small>logging in with your osu account does nothing</small>
|
||||||
|
|
||||||
|
<div class="nav-bar">
|
||||||
|
<a href="/">home</a>
|
||||||
|
|
||||||
|
{{ if .LoggedIn }}
|
||||||
|
<a href="/logout">logout</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="/login">login</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ template "content" . }}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
108
web/web.go
108
web/web.go
|
@ -1,15 +1,12 @@
|
||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -32,80 +29,60 @@ var (
|
||||||
cache = memoize.NewMemoizer(90*time.Second, 10*time.Minute)
|
cache = memoize.NewMemoizer(90*time.Second, 10*time.Minute)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Web struct {
|
||||||
|
config *config.Config
|
||||||
|
api *osuapi.Osuapi
|
||||||
|
hc *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
func RunWeb(config *config.Config, api *osuapi.Osuapi) {
|
func RunWeb(config *config.Config, api *osuapi.Osuapi) {
|
||||||
hc := http.Client{
|
hc := &http.Client{
|
||||||
Timeout: 10 * time.Second,
|
Timeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.Debug {
|
web := Web{config, api, hc}
|
||||||
|
web.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (web *Web) Run() {
|
||||||
|
if !web.config.Debug {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Use(gin.Recovery())
|
r.Use(gin.Recovery())
|
||||||
r.Use(static.Serve("/static", static.LocalFile("web/static", false)))
|
r.Use(static.Serve("/static", static.LocalFile("web/static", false)))
|
||||||
r.Use(sessions.Sessions("mysession", sessions.NewCookieStore([]byte(config.Web.SessionSecret))))
|
r.Use(sessions.Sessions("mysession", sessions.NewCookieStore([]byte(web.config.Web.SessionSecret))))
|
||||||
|
|
||||||
r.HTMLRender = ginview.New(goview.Config{
|
r.HTMLRender = ginview.New(goview.Config{
|
||||||
Root: "web/templates",
|
Root: "web/templates",
|
||||||
DisableCache: config.Debug,
|
Master: "master.html",
|
||||||
|
DisableCache: web.config.Debug,
|
||||||
})
|
})
|
||||||
|
|
||||||
r.GET("/logout", func(c *gin.Context) {
|
r.GET("/logout", web.logout)
|
||||||
session := sessions.Default(c)
|
|
||||||
session.Delete("access_token")
|
|
||||||
session.Save()
|
|
||||||
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
r.GET("/login", web.login)
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/login", func(c *gin.Context) {
|
r.GET("/login/callback", web.loginCallback)
|
||||||
url := url.URL{
|
|
||||||
Scheme: "https",
|
|
||||||
Host: "osu.ppy.sh",
|
|
||||||
Path: "/oauth/authorize",
|
|
||||||
}
|
|
||||||
q := url.Query()
|
|
||||||
q.Set("client_id", config.Oauth.ClientId)
|
|
||||||
q.Set("redirect_uri", config.Web.ServedAt+"/login/callback")
|
|
||||||
q.Set("response_type", "code")
|
|
||||||
q.Set("scope", "identify public")
|
|
||||||
q.Set("state", "urmom")
|
|
||||||
url.RawQuery = q.Encode()
|
|
||||||
fmt.Println("redirecting to", url.String())
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url.String())
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/login/callback", func(c *gin.Context) {
|
r.GET("/map/:userId/:mapId/versions", web.mapVersions)
|
||||||
receivedCode := c.Query("code")
|
|
||||||
|
|
||||||
bodyQuery := url.Values{}
|
r.GET("/map/:userId/:mapId/patch/:hash", web.mapPatch)
|
||||||
bodyQuery.Set("client_id", config.Oauth.ClientId)
|
|
||||||
bodyQuery.Set("client_secret", config.Oauth.ClientSecret)
|
|
||||||
bodyQuery.Set("code", receivedCode)
|
|
||||||
bodyQuery.Set("grant_type", "authorization_code")
|
|
||||||
bodyQuery.Set("redirect_uri", config.Web.ServedAt+"/login/callback")
|
|
||||||
body := strings.NewReader(bodyQuery.Encode())
|
|
||||||
resp, _ := hc.Post("https://osu.ppy.sh/oauth/token", "application/x-www-form-urlencoded", body)
|
|
||||||
respBody, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
type OsuToken struct {
|
|
||||||
TokenType string `json:"token_type"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
}
|
|
||||||
var token OsuToken
|
|
||||||
_ = json.Unmarshal(respBody, &token)
|
|
||||||
fmt.Println("TOKEN", token)
|
|
||||||
|
|
||||||
session := sessions.Default(c)
|
|
||||||
session.Set("access_token", token.AccessToken)
|
|
||||||
session.Save()
|
|
||||||
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/", func(c *gin.Context) {
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
beatmapSets := web.listRepos()
|
||||||
|
c.HTML(http.StatusOK, "index.html", gin.H{
|
||||||
|
"LoggedIn": isLoggedIn(c),
|
||||||
|
"Beatmapsets": beatmapSets,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
addr := fmt.Sprintf("%s:%d", web.config.Web.Host, web.config.Web.Port)
|
||||||
|
r.Run(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLoggedIn(c *gin.Context) bool {
|
||||||
session := sessions.Default(c)
|
session := sessions.Default(c)
|
||||||
var accessToken string
|
var accessToken string
|
||||||
loggedIn := false
|
loggedIn := false
|
||||||
|
@ -116,24 +93,13 @@ func RunWeb(config *config.Config, api *osuapi.Osuapi) {
|
||||||
loggedIn = true
|
loggedIn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return loggedIn
|
||||||
beatmapSets := getRepos(config, api)
|
|
||||||
|
|
||||||
// render with master
|
|
||||||
c.HTML(http.StatusOK, "index.html", gin.H{
|
|
||||||
"LoggedIn": loggedIn,
|
|
||||||
"Beatmapsets": beatmapSets,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%d", config.Web.Host, config.Web.Port)
|
|
||||||
r.Run(addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRepos(config *config.Config, api *osuapi.Osuapi) []osuapi.Beatmapset {
|
func (web *Web) listRepos() []osuapi.Beatmapset {
|
||||||
expensive := func() (interface{}, error) {
|
expensive := func() (interface{}, error) {
|
||||||
repos := make([]int, 0)
|
repos := make([]int, 0)
|
||||||
reposDir := config.Repos
|
reposDir := web.config.Repos
|
||||||
users, _ := ioutil.ReadDir(reposDir)
|
users, _ := ioutil.ReadDir(reposDir)
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
|
@ -155,7 +121,7 @@ func getRepos(config *config.Config, api *osuapi.Osuapi) []osuapi.Beatmapset {
|
||||||
for i, repo := range repos {
|
for i, repo := range repos {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(i int, repo int) {
|
go func(i int, repo int) {
|
||||||
bs, _ := api.GetBeatmapSet(repo)
|
bs, _ := web.api.GetBeatmapSet(repo)
|
||||||
beatmapSets[i] = bs
|
beatmapSets[i] = bs
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i, repo)
|
}(i, repo)
|
||||||
|
|
Loading…
Reference in a new issue