Skip to content

Commit

Permalink
feat: update soundcloud feeder
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse0Michael committed Sep 7, 2023
1 parent f1f8cc0 commit a08067f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 13 deletions.
16 changes: 15 additions & 1 deletion cmd/fetcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log/slog"
"os"
"os/signal"
"strings"
"syscall"

"github.com/jesse0michael/fetcher/internal/server"
Expand All @@ -19,7 +20,7 @@ type Config struct {
}

func main() {
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})))
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: LogLevel()})))

// Setup context that will cancel on signalled termination
ctx, cancel := context.WithCancel(context.Background())
Expand Down Expand Up @@ -52,3 +53,16 @@ func main() {
srvr.Close()
slog.Info("exiting")
}

func LogLevel() slog.Leveler {
switch strings.ToUpper(os.Getenv("LOG_LEVEL")) {
case "DEBUG":
return slog.LevelDebug
case "WARN":
return slog.LevelWarn
case "ERROR":
return slog.LevelError
default:
return slog.LevelInfo
}
}
11 changes: 6 additions & 5 deletions internal/service/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
)

type Config struct {
Twitter TwitterConfig
Instagram InstagramConfig
Count int `envconfig:"FETCHER_COUNT" default:"50"`
ProxyURL string `envconfig:"FETCHER_PROXY_URL" default:"https://fetcher-ho4joes5va-uw.a.run.app/proxy"`
Twitter TwitterConfig
Instagram InstagramConfig
SoundCloud SoundCloudConfig
Count int `envconfig:"FETCHER_COUNT" default:"50"`
ProxyURL string `envconfig:"FETCHER_PROXY_URL" default:"https://fetcher-ho4joes5va-uw.a.run.app/proxy"`
}

type Feeder interface {
Expand Down Expand Up @@ -56,7 +57,7 @@ func NewFetcher(cfg Config) *Fetcher {
blogger: NewBlogger(),
twitter: twitter,
instagram: instagram,
soundCloud: NewSoundCloud(),
soundCloud: NewSoundCloud(cfg.SoundCloud),
swarm: NewSwarm(),
deviantArt: NewDeviantArt(),
}
Expand Down
70 changes: 63 additions & 7 deletions internal/service/soundcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,84 @@ import (
"context"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"strconv"
"time"

"github.com/tidwall/gjson"
)

type SoundCloudConfig struct {
Count int `envconfig:"SOUND_CLOUD_COUNT" default:"20"`
ClientID string `envconfig:"SOUND_CLOUD_CLIENT_ID"`
ClientSecret string `envconfig:"SOUND_CLOUD_CLIENT_SECRET"`
}

type SoundCloud struct {
cfg SoundCloudConfig
authToken string
}

func NewSoundCloud(cfg SoundCloudConfig) *SoundCloud {
return &SoundCloud{cfg: cfg}
}

func NewSoundCloud() *SoundCloud {
return &SoundCloud{}
func (s *SoundCloud) auth(ctx context.Context) (string, error) {
if s.authToken != "" {
return s.authToken, nil
}

auth, err := s.authenticate(ctx)
if err != nil {
return "", err
}
s.authToken = auth
return auth, nil
}

func (s *SoundCloud) authenticate(ctx context.Context) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
"https://api.soundcloud.com/oauth2/token", nil)
if err != nil {
return "", err
}
q := url.Values{}
q.Add("client_id", s.cfg.ClientID)
q.Add("client_secret", s.cfg.ClientSecret)
q.Add("grant_type", "client_credentials")
req.URL.RawQuery = q.Encode()

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
slog.With("feeder", "soundcloud", "body", string(body), "status", resp.StatusCode).
Debug("soundcloud authentication response")

return gjson.GetBytes(body, "access_token").String(), nil
}

func (s *SoundCloud) Feed(_ context.Context, id string) ([]FeedItem, error) {
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet,
fmt.Sprintf("https://api.soundcloud.com/users/%s/favorites", id), nil)
func (s *SoundCloud) Feed(ctx context.Context, id string) ([]FeedItem, error) {
auth, err := s.auth(ctx)
if err != nil {
return nil, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
fmt.Sprintf("https://api.soundcloud.com/users/%s/likes/tracks", id), nil)
if err != nil {
return nil, err
}
q := url.Values{}
q.Add("client_id", "f330c0bb90f1c89a15e78ece83e21856")
q.Add("limit", "20")
q.Add("limit", strconv.Itoa(s.cfg.Count))
req.URL.RawQuery = q.Encode()
req.Header.Set("Authorization", fmt.Sprintf("OAuth %s", auth))

resp, err := http.DefaultClient.Do(req)
if err != nil {
Expand All @@ -38,6 +92,8 @@ func (s *SoundCloud) Feed(_ context.Context, id string) ([]FeedItem, error) {
if err != nil {
return nil, err
}
slog.With("feeder", "soundcloud", "body", string(body), "status", resp.StatusCode).
Debug("soundcloud response")

items := []FeedItem{}
for _, sound := range gjson.ParseBytes(body).Array() {
Expand Down

0 comments on commit a08067f

Please sign in to comment.