From 18d81548f4178767a25a99080ab5dfefb041be7d Mon Sep 17 00:00:00 2001 From: Laptop Date: Sat, 7 Dec 2024 13:15:48 +0200 Subject: [PATCH] see user followers, who the user follows and popular tracks of user --- lib/sc/user.go | 96 ++++++++++++++++++++++++++++++++++++++++---- main.go | 92 ++++++++++++++++++++++++++++++++++++++++++ templates/user.templ | 77 ++++++++++++++++++++++++++++++++--- 3 files changed, 253 insertions(+), 12 deletions(-) diff --git a/lib/sc/user.go b/lib/sc/user.go index d9efb8e..8c72f1d 100644 --- a/lib/sc/user.go +++ b/lib/sc/user.go @@ -28,13 +28,13 @@ type User struct { FullName string `json:"full_name"` Kind string `json:"kind"` // should always be "user"! LastModified string `json:"last_modified"` - //Liked int `json:"likes_count"` - Permalink string `json:"permalink"` - Playlists int64 `json:"playlist_count"` - Tracks int64 `json:"track_count"` - ID string `json:"urn"` - Username string `json:"username"` - Verified bool `json:"verified"` + Liked int64 `json:"likes_count"` + Permalink string `json:"permalink"` + Playlists int64 `json:"playlist_count"` + Tracks int64 `json:"track_count"` + ID string `json:"urn"` + Username string `json:"username"` + Verified bool `json:"verified"` WebProfiles []Link } @@ -330,3 +330,85 @@ func (u *User) GetWebProfiles() error { return json.Unmarshal(data, &u.WebProfiles) } + +func (u *User) GetRelated(prefs cfg.Preferences) ([]*User, error) { + cid, err := GetClientID() + if err != nil { + return nil, err + } + + p := Paginated[*User]{ + Next: "https://" + api + "/users/" + u.ID + "/relatedartists?page_size=20&client_id=" + cid, + } + + err = p.Proceed(true) + if err != nil { + return nil, err + } + + for _, u := range p.Collection { + u.Fix(false) + u.Postfix(prefs) + } + + return p.Collection, nil +} + +func (u *User) GetTopTracks(prefs cfg.Preferences) ([]*Track, error) { + cid, err := GetClientID() + if err != nil { + return nil, err + } + + p := Paginated[*Track]{ + Next: "https://" + api + "/users/" + u.ID + "/toptracks?client_id=" + cid, + } + + err = p.Proceed(true) + if err != nil { + return nil, err + } + + for _, t := range p.Collection { + t.Fix(false, false) + t.Postfix(prefs, false) + } + + return p.Collection, nil +} + +func (u User) GetFollowers(prefs cfg.Preferences, args string) (*Paginated[*User], error) { + p := Paginated[*User]{ + Next: "https://" + api + "/users/" + u.ID + "/followers" + args, + } + + err := p.Proceed(true) + if err != nil { + return nil, err + } + + for _, u := range p.Collection { + u.Fix(false) + u.Postfix(prefs) + } + + return &p, nil +} + +func (u User) GetFollowing(prefs cfg.Preferences, args string) (*Paginated[*User], error) { + p := Paginated[*User]{ + Next: "https://" + api + "/users/" + u.ID + "/followings" + args, + } + + err := p.Proceed(true) + if err != nil { + return nil, err + } + + for _, u := range p.Collection { + u.Fix(false) + u.Postfix(prefs) + } + + return &p, nil +} diff --git a/main.go b/main.go index f7f7445..0169726 100644 --- a/main.go +++ b/main.go @@ -344,6 +344,75 @@ func main() { return templates.Base(user.Username, templates.UserLikes(prefs, user, p), templates.UserHeader(user)).Render(context.Background(), c) }) + app.Get("/:user/popular-tracks", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + user, err := sc.GetUser(c.Params("user")) + if err != nil { + log.Printf("error getting %s (popular-tracks): %s\n", c.Params("user"), err) + return err + } + user.Postfix(prefs) + + p, err := user.GetTopTracks(prefs) + if err != nil { + log.Printf("error getting %s popular tracks: %s\n", c.Params("user"), err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base(user.Username, templates.UserTopTracks(prefs, user, p), templates.UserHeader(user)).Render(context.Background(), c) + }) + + app.Get("/:user/followers", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + user, err := sc.GetUser(c.Params("user")) + if err != nil { + log.Printf("error getting %s (followers): %s\n", c.Params("user"), err) + return err + } + user.Postfix(prefs) + + p, err := user.GetFollowers(prefs, c.Query("pagination", "?limit=20")) + if err != nil { + log.Printf("error getting %s followers: %s\n", c.Params("user"), err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base(user.Username, templates.UserFollowers(prefs, user, p), templates.UserHeader(user)).Render(context.Background(), c) + }) + + app.Get("/:user/following", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + user, err := sc.GetUser(c.Params("user")) + if err != nil { + log.Printf("error getting %s (following): %s\n", c.Params("user"), err) + return err + } + user.Postfix(prefs) + + p, err := user.GetFollowing(prefs, c.Query("pagination", "?limit=20")) + if err != nil { + log.Printf("error getting %s following: %s\n", c.Params("user"), err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base(user.Username, templates.UserFollowing(prefs, user, p), templates.UserHeader(user)).Render(context.Background(), c) + }) + app.Get("/:user/:track", func(c *fiber.Ctx) error { prefs, err := preferences.Get(c) if err != nil { @@ -486,5 +555,28 @@ func main() { return templates.Base(playlist.Title+" by "+playlist.Author.Username, templates.Playlist(prefs, playlist), templates.PlaylistHeader(playlist)).Render(context.Background(), c) }) + app.Get("/:user/_/related", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + user, err := sc.GetUser(c.Params("user")) + if err != nil { + log.Printf("error getting %s (related): %s\n", c.Params("user"), err) + return err + } + user.Postfix(prefs) + + r, err := user.GetRelated(prefs) + if err != nil { + log.Printf("error getting %s related users: %s\n", c.Params("user"), err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base(user.Username, templates.UserRelated(prefs, user, r), templates.UserHeader(user)).Render(context.Background(), c) + }) + log.Fatal(app.Listen(cfg.Addr)) } diff --git a/templates/user.templ b/templates/user.templ index 58fbf7d..dd1b5ba 100644 --- a/templates/user.templ +++ b/templates/user.templ @@ -63,8 +63,9 @@ templ UserBase(prefs cfg.Preferences, u sc.User) { @Description(prefs, u.Description, nil) }
-

{ strconv.FormatInt(u.Followers, 10) } followers

-

{ strconv.FormatInt(u.Following, 10) } following

+

{ strconv.FormatInt(u.Followers, 10) } followers

+

{ strconv.FormatInt(u.Following, 10) } followings

+

{ strconv.FormatInt(u.Liked, 10) } liked

{ strconv.FormatInt(u.Tracks, 10) } tracks

{ strconv.FormatInt(u.Playlists, 10) } playlists & albums


@@ -82,7 +83,7 @@ type btn struct { templ UserButtons(current string, user string) {
// this part is the tedious one now, because formatting breaks if i space the list out with newlines - for _, b := range [6]btn{{"tracks", "", false},{"playlists", "/sets",false},{"albums", "/albums", false},{"reposts","/reposts", false},{"likes", "/likes", false},{"view on soundcloud", "https://soundcloud.com/"+user, true}} { + for _, b := range [7]btn{{"tracks", "", false},{"popular tracks", "/popular-tracks", false},{"playlists", "/sets",false},{"albums", "/albums", false},{"reposts","/reposts", false},{"related", "/_/related", false},{"view on soundcloud", "https://soundcloud.com/"+user, true}} { if b.text == current { { b.text } } else { @@ -176,8 +177,8 @@ templ UserReposts(prefs cfg.Preferences, u sc.User, p *sc.Paginated[*sc.Repost]) templ UserLikes(prefs cfg.Preferences, u sc.User, p *sc.Paginated[*sc.Like]) { @UserBase(prefs, u) - @UserButtons("likes", u.Permalink) -
+ @UserButtons("", u.Permalink) +

Likes

if len(p.Collection) != 0 {
for _, like := range p.Collection { @@ -196,6 +197,72 @@ templ UserLikes(prefs cfg.Preferences, u sc.User, p *sc.Paginated[*sc.Like]) { } } +templ UserRelated(prefs cfg.Preferences, u sc.User, r []*sc.User) { + @UserBase(prefs, u) + @UserButtons("related", u.Permalink) +
+ if len(r) != 0 { +
+ for _, u := range r { + @UserItem(u) + } +
+ } else { + no related users + } +} + +templ UserTopTracks(prefs cfg.Preferences, u sc.User, t []*sc.Track) { + @UserBase(prefs, u) + @UserButtons("popular-tracks", u.Permalink) +
+ if len(t) != 0 { +
+ for _, track := range t { + @TrackItem(track, false, "") + } +
+ } else { + no popular tracks + } +} + +templ UserFollowers(prefs cfg.Preferences, u sc.User, p *sc.Paginated[*sc.User]) { + @UserBase(prefs, u) + @UserButtons("", u.Permalink) +

Followers

+ if len(p.Collection) != 0 { +
+ for _, user := range p.Collection { + @UserItem(user) + } +
+ if p.Next != "" && len(p.Collection) != int(p.Total) { + more users + } + } else { + no more users + } +} + +templ UserFollowing(prefs cfg.Preferences, u sc.User, p *sc.Paginated[*sc.User]) { + @UserBase(prefs, u) + @UserButtons("", u.Permalink) +

Following

+ if len(p.Collection) != 0 { +
+ for _, user := range p.Collection { + @UserItem(user) + } +
+ if p.Next != "" && len(p.Collection) != int(p.Total) { + more users + } + } else { + no more users + } +} + templ SearchUsers(p *sc.Paginated[*sc.User]) { Found { strconv.FormatInt(p.Total, 10) } users