ci / module boundaries / boundaries (push) Successful in 6s
ci / api / api (push) Successful in 47s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m2s
ci / db / db (push) Successful in 1m4s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m30s
ci / ts / ts (packages + web) (push) Successful in 2m54s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m14s
59 lines
1.3 KiB
Go
59 lines
1.3 KiB
Go
package playback
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"pipu/api/internal/api/gen"
|
|
"pipu/api/internal/auth"
|
|
"pipu/api/internal/library"
|
|
"pipu/api/internal/platform/sign"
|
|
)
|
|
|
|
type ReactionReader interface {
|
|
Reactions(context.Context, uuid.UUID, []uuid.UUID) (map[uuid.UUID]string, error)
|
|
}
|
|
|
|
// Personalizer decorates catalog DTOs independently of HTTP handlers.
|
|
type Personalizer struct {
|
|
store ReactionReader
|
|
signer *sign.Signer
|
|
now func() time.Time
|
|
}
|
|
|
|
var _ library.Personalizer = (*Personalizer)(nil)
|
|
|
|
func NewPersonalizer(store ReactionReader, signer *sign.Signer) *Personalizer {
|
|
return &Personalizer{store: store, signer: signer, now: func() time.Time { return time.Now().UTC() }}
|
|
}
|
|
|
|
// Personalize реализует library.Personalizer.
|
|
func (h *Personalizer) Personalize(ctx context.Context, rows []library.TrackRow, out []gen.Track) error {
|
|
p, ok := auth.PrincipalFrom(ctx)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
ids := make([]uuid.UUID, len(rows))
|
|
for i, r := range rows {
|
|
ids[i] = r.ID
|
|
}
|
|
reactions, err := h.store.Reactions(ctx, p.UserID, ids)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
now := h.now()
|
|
for i := range out {
|
|
if out[i].Available {
|
|
u := StreamURL(h.signer, p.UserID, rows[i].ID, now)
|
|
out[i].StreamUrl = &u
|
|
}
|
|
if r, ok := reactions[rows[i].ID]; ok {
|
|
rr := gen.Reaction(r)
|
|
out[i].Reaction = &rr
|
|
}
|
|
}
|
|
return nil
|
|
}
|