Skip to content

Commit

Permalink
feat(structure): restructure codebase
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Gleich <[email protected]>
  • Loading branch information
gleich committed Jul 30, 2024
1 parent 399d84b commit 696298a
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 88 deletions.
56 changes: 5 additions & 51 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,22 @@
package main

import (
"context"
"net/http"
"time"

"github.com/caarlos0/env/v11"
"github.com/gleich/lcp-v2/pkg/apis/github"
"github.com/gleich/lcp-v2/pkg/apis/steam"
"github.com/gleich/lcp-v2/pkg/apis/strava"
"github.com/gleich/lcp-v2/pkg/cache"
"github.com/gleich/lcp-v2/pkg/secrets"
"github.com/gleich/lumber/v2"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/joho/godotenv"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
)

func main() {
lumber.Info("booted")

err := godotenv.Load()
if err != nil {
lumber.Fatal(err, "loading .env file failed")
}
loadedSecrets, err := env.ParseAs[secrets.SecretsData]()
if err != nil {
lumber.Fatal(err, "parsing required env vars failed")
}
secrets.SECRETS = loadedSecrets
lumber.Success("loaded secrets")
secrets.Load()

r := chi.NewRouter()
r.Use(middleware.Logger)
Expand All @@ -43,40 +25,12 @@ func main() {
r.HandleFunc("/", rootRedirect)
r.HandleFunc("/metrics", promhttp.Handler().ServeHTTP)

githubTokenSource := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: secrets.SECRETS.GitHubAccessToken},
)
githubHttpClient := oauth2.NewClient(context.Background(), githubTokenSource)
githubClient := githubv4.NewClient(githubHttpClient)
githubCache := cache.NewCache("github", github.FetchPinnedRepos(githubClient))
r.Get("/github/cache", githubCache.ServeHTTP())
lumber.Success("setup github cache")
go githubCache.StartPeriodicUpdate(func() []github.Repository { return github.FetchPinnedRepos(githubClient) }, 2*time.Minute)

stravaTokens := strava.LoadTokens()
stravaTokens.RefreshIfNeeded()
minioClient, err := minio.New(secrets.SECRETS.MinioEndpoint, &minio.Options{
Creds: credentials.NewStaticV4(secrets.SECRETS.MinioAccessKeyID, secrets.SECRETS.MinioSecretKey, ""),
Secure: true,
})
if err != nil {
lumber.Fatal(err, "failed to create minio client")
}
stravaActivities := strava.FetchActivities(*minioClient, stravaTokens)
stravaCache := cache.NewCache("strava", stravaActivities)
r.Get("/strava/cache", stravaCache.ServeHTTP())
r.Post("/strava/event", strava.EventRoute(stravaCache, *minioClient, stravaTokens))
r.Get("/strava/event", strava.ChallengeRoute)
lumber.Success("setup strava cache")

games := steam.FetchRecentlyPlayedGames()
steamCache := cache.NewCache("steam", games)
r.Get("/steam/cache", steamCache.ServeHTTP())
lumber.Success("setup steam cache")
go steamCache.StartPeriodicUpdate(steam.FetchRecentlyPlayedGames, 10*time.Minute)
github.Setup(r)
strava.Setup(r)
steam.Setup(r)

lumber.Info("starting server")
err = http.ListenAndServe(":8000", r)
err := http.ListenAndServe(":8000", r)
if err != nil {
lumber.Fatal(err, "failed to start router")
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/apis/github/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package github

import (
"context"
"time"

"github.com/gleich/lcp-v2/pkg/cache"
"github.com/gleich/lcp-v2/pkg/secrets"
"github.com/gleich/lumber/v2"
"github.com/go-chi/chi/v5"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
)

func Setup(router *chi.Mux) {
githubTokenSource := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: secrets.SECRETS.GitHubAccessToken},
)
githubHttpClient := oauth2.NewClient(context.Background(), githubTokenSource)
githubClient := githubv4.NewClient(githubHttpClient)
githubCache := cache.NewCache("github", FetchPinnedRepos(githubClient))
router.Get("/github/cache", githubCache.ServeHTTP())
go githubCache.StartPeriodicUpdate(func() []repository { return FetchPinnedRepos(githubClient) }, 2*time.Minute)
lumber.Success("setup github cache")
}
14 changes: 7 additions & 7 deletions pkg/apis/github/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/shurcooL/githubv4"
)

type PinnedItemsQuery struct {
type pinnedItemsQuery struct {
Viewer struct {
PinnedItems struct {
Nodes []struct {
Expand All @@ -34,7 +34,7 @@ type PinnedItemsQuery struct {
}
}

type Repository struct {
type repository struct {
Name string `json:"name"`
Owner string `json:"owner"`
Language string `json:"language"`
Expand All @@ -46,17 +46,17 @@ type Repository struct {
URL string `json:"url"`
}

func FetchPinnedRepos(client *githubv4.Client) []Repository {
var query PinnedItemsQuery
func FetchPinnedRepos(client *githubv4.Client) []repository {
var query pinnedItemsQuery
err := client.Query(context.Background(), &query, nil)
if err != nil {
lumber.Error(err, "querying github's graphql API failed")
return nil
}

var repository []Repository
var repositories []repository
for _, node := range query.Viewer.PinnedItems.Nodes {
repository = append(repository, Repository{
repositories = append(repositories, repository{
Name: string(node.Repository.Name),
Owner: string(node.Repository.Owner.Login),
Language: string(node.Repository.PrimaryLanguage.Name),
Expand All @@ -68,5 +68,5 @@ func FetchPinnedRepos(client *githubv4.Client) []Repository {
URL: fmt.Sprint(node.Repository.URL.URL),
})
}
return repository
return repositories
}
8 changes: 4 additions & 4 deletions pkg/apis/steam/achievements.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type schemaGameResponse struct {
} `json:"game"`
}

type Achievement struct {
type achievement struct {
ApiName string `json:"api_name"`
Achieved bool `json:"achieved"`
Icon string `json:"icon"`
Expand All @@ -45,7 +45,7 @@ type Achievement struct {
UnlockTime *time.Time `json:"unlock_time"`
}

func FetchGameAchievements(appID int32) (*float32, *[]Achievement) {
func fetchGameAchievements(appID int32) (*float32, *[]achievement) {
params := url.Values{
"key": {secrets.SECRETS.SteamKey},
"steamid": {secrets.SECRETS.SteamID},
Expand Down Expand Up @@ -114,15 +114,15 @@ func FetchGameAchievements(appID int32) (*float32, *[]Achievement) {
return nil, nil
}

var achievements []Achievement
var achievements []achievement
for _, playerAchievement := range *playerAchievements.PlayerStats.Achievements {
for _, schemaAchievement := range gameSchema.Game.GameStats.Achievements {
if playerAchievement.ApiName == schemaAchievement.Name {
var unlockTime time.Time
if playerAchievement.UnlockTime != nil && *playerAchievement.UnlockTime != 0 {
unlockTime = time.Unix(*playerAchievement.UnlockTime, 0)
}
achievements = append(achievements, Achievement{
achievements = append(achievements, achievement{
ApiName: playerAchievement.ApiName,
Achieved: playerAchievement.Achieved == 1,
Icon: schemaAchievement.Icon,
Expand Down
12 changes: 6 additions & 6 deletions pkg/apis/steam/games.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type ownedGamesResponse struct {
} `json:"response"`
}

type Game struct {
type game struct {
Name string `json:"name"`
AppID int32 `json:"app_id"`
IconURL string `json:"icon_url"`
Expand All @@ -35,10 +35,10 @@ type Game struct {
HeaderURL string `json:"header_url"`
LibraryURL *string `json:"library_url"`
AchievementProgress *float32 `json:"achievement_progress"`
Achievements *[]Achievement `json:"achievements"`
Achievements *[]achievement `json:"achievements"`
}

func FetchRecentlyPlayedGames() []Game {
func fetchRecentlyPlayedGames() []game {
params := url.Values{
"key": {secrets.SECRETS.SteamKey},
"steamid": {secrets.SECRETS.SteamID},
Expand Down Expand Up @@ -75,7 +75,7 @@ func FetchRecentlyPlayedGames() []Game {
})
ownedGames.Response.Games = ownedGames.Response.Games[:10]

var games []Game
var games []game
for _, g := range ownedGames.Response.Games {
libraryURL := fmt.Sprintf("https://shared.akamai.steamstatic.com/store_item_assets/steam/apps/%d/library_600x900.jpg", g.AppID)
libraryImageResponse, err := http.Get(libraryURL)
Expand All @@ -90,9 +90,9 @@ func FetchRecentlyPlayedGames() []Game {
libraryURLPtr = &libraryURL
}

achievementPercentage, achievements := FetchGameAchievements(g.AppID)
achievementPercentage, achievements := fetchGameAchievements(g.AppID)

games = append(games, Game{
games = append(games, game{
Name: g.Name,
AppID: g.AppID,
IconURL: fmt.Sprintf("https://media.steampowered.com/steamcommunity/public/images/apps/%d/%s.jpg", g.AppID, g.ImgIconURL),
Expand Down
17 changes: 17 additions & 0 deletions pkg/apis/steam/steam.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package steam

import (
"time"

"github.com/gleich/lcp-v2/pkg/cache"
"github.com/gleich/lumber/v2"
"github.com/go-chi/chi/v5"
)

func Setup(router *chi.Mux) {
games := fetchRecentlyPlayedGames()
steamCache := cache.NewCache("steam", games)
router.Get("/steam/cache", steamCache.ServeHTTP())
go steamCache.StartPeriodicUpdate(fetchRecentlyPlayedGames, 10*time.Minute)
lumber.Success("setup steam cache")
}
14 changes: 7 additions & 7 deletions pkg/apis/strava/activities.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/minio/minio-go/v7"
)

type Activity struct {
type activity struct {
Name string `json:"name"`
SportType string `json:"sport_type"`
StartDate time.Time `json:"start_date"`
Expand All @@ -37,7 +37,7 @@ type Activity struct {
ID uint64 `json:"id"`
}

func FetchActivities(minioClient minio.Client, tokens Tokens) []Activity {
func fetchActivities(minioClient minio.Client, tokens tokens) []activity {
req, err := http.NewRequest("GET", "https://www.strava.com/api/v3/athlete/activities", nil)
if err != nil {
lumber.Error(err, "Failed to create new request")
Expand All @@ -58,7 +58,7 @@ func FetchActivities(minioClient minio.Client, tokens Tokens) []Activity {
return nil
}

var activities []Activity
var activities []activity
err = json.Unmarshal(body, &activities)
if err != nil {
lumber.Error(err, "failed to parse json")
Expand All @@ -69,11 +69,11 @@ func FetchActivities(minioClient minio.Client, tokens Tokens) []Activity {
activities = activities[:6]

for i, activity := range activities {
mapData := FetchMap(activity.Map.SummaryPolyline)
UploadMap(minioClient, activity.ID, mapData)
activities[i].Map.MapBlurImage = MapBlurData(mapData)
mapData := fetchMap(activity.Map.SummaryPolyline)
uploadMap(minioClient, activity.ID, mapData)
activities[i].Map.MapBlurImage = mapBlurData(mapData)
}
RemoveOldMaps(minioClient, activities)
removeOldMaps(minioClient, activities)

lumber.Success("uploaded", len(activities), "maps to minio")

Expand Down
8 changes: 4 additions & 4 deletions pkg/apis/strava/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type event struct {
Updates map[string]string `json:"updates"`
}

func EventRoute(stravaCache *cache.Cache[[]Activity], minioClient minio.Client, tokens Tokens) http.HandlerFunc {
func eventRoute(stravaCache *cache.Cache[[]activity], minioClient minio.Client, tokens tokens) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
body, err := io.ReadAll(r.Body)
Expand All @@ -43,12 +43,12 @@ func EventRoute(stravaCache *cache.Cache[[]Activity], minioClient minio.Client,
return
}

tokens.RefreshIfNeeded()
stravaCache.Update(FetchActivities(minioClient, tokens))
tokens.refreshIfNeeded()
stravaCache.Update(fetchActivities(minioClient, tokens))
})
}

func ChallengeRoute(w http.ResponseWriter, r *http.Request) {
func challengeRoute(w http.ResponseWriter, r *http.Request) {
verifyToken := r.URL.Query().Get("hub.verify_token")
if verifyToken != secrets.SECRETS.StravaVerifyToken {
w.WriteHeader(http.StatusUnauthorized)
Expand Down
8 changes: 4 additions & 4 deletions pkg/apis/strava/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

const bucketName = "mapbox-maps"

func FetchMap(polyline string) []byte {
func fetchMap(polyline string) []byte {
var (
lineWidth = 2.0
lineColor = "000"
Expand Down Expand Up @@ -45,7 +45,7 @@ func FetchMap(polyline string) []byte {
return b.Bytes()
}

func MapBlurData(data []byte) *string {
func mapBlurData(data []byte) *string {
reader := bytes.NewReader(data)
parsedPNG, err := png.Decode(reader)
if err != nil {
Expand Down Expand Up @@ -77,7 +77,7 @@ func MapBlurData(data []byte) *string {
return &blurDataURI
}

func UploadMap(minioClient minio.Client, id uint64, data []byte) {
func uploadMap(minioClient minio.Client, id uint64, data []byte) {
reader := bytes.NewReader(data)
size := int64(len(data))

Expand All @@ -94,7 +94,7 @@ func UploadMap(minioClient minio.Client, id uint64, data []byte) {
}
}

func RemoveOldMaps(minioClient minio.Client, activities []Activity) {
func removeOldMaps(minioClient minio.Client, activities []activity) {
var validKeys []string
for _, activity := range activities {
validKeys = append(validKeys, fmt.Sprintf("%d.png", activity.ID))
Expand Down
29 changes: 29 additions & 0 deletions pkg/apis/strava/strava.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package strava

import (
"github.com/gleich/lcp-v2/pkg/cache"
"github.com/gleich/lcp-v2/pkg/secrets"
"github.com/gleich/lumber/v2"
"github.com/go-chi/chi/v5"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)

func Setup(router *chi.Mux) {
stravaTokens := loadTokens()
stravaTokens.refreshIfNeeded()
minioClient, err := minio.New(secrets.SECRETS.MinioEndpoint, &minio.Options{
Creds: credentials.NewStaticV4(secrets.SECRETS.MinioAccessKeyID, secrets.SECRETS.MinioSecretKey, ""),
Secure: true,
})
if err != nil {
lumber.Fatal(err, "failed to create minio client")
}
stravaActivities := fetchActivities(*minioClient, stravaTokens)
stravaCache := cache.NewCache("strava", stravaActivities)
router.Get("/strava/cache", stravaCache.ServeHTTP())
router.Post("/strava/event", eventRoute(stravaCache, *minioClient, stravaTokens))
router.Get("/strava/event", challengeRoute)

lumber.Success("setup strava cache")
}
Loading

0 comments on commit 696298a

Please sign in to comment.