Files
go-midjourney/recent_jobs.go
2022-09-15 23:06:08 +01:00

204 lines
3.8 KiB
Go

package midjourney
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
)
const FromDateFormat = "2006-01-02 15:04:05.999999"
var ErrUserIDRequired = fmt.Errorf("%w: user id required", Err)
type Order string
const (
OrderHot Order = "hot"
OrderNew Order = "new"
OrderOldest Order = "oldest"
OrderTopToday Order = "top-today"
OrderTopWeekly Order = "top-weekly"
OrderTopMonth Order = "top-month"
OrderTopAll Order = "top-all"
OrderLikedTime Order = "liked_timestamp"
)
type RecentJobsQuery struct {
Amount int
JobType JobType
OrderBy Order
JobStatus JobStatus
UserID string
UserIDLiked string
FromDate time.Time
Page int
Prompt string
Personal bool
Dedupe bool
RefreshAPI int
}
func (rjq *RecentJobsQuery) Values() url.Values {
v := url.Values{}
if rjq.Amount != 0 {
v.Set("amount", strconv.Itoa(rjq.Amount))
}
if rjq.JobType != "" {
v.Set("jobType", string(rjq.JobType))
}
if rjq.OrderBy != "" {
v.Set("orderBy", string(rjq.OrderBy))
}
if rjq.JobStatus != "" {
v.Set("jobStatus", string(rjq.JobStatus))
}
if rjq.UserID != "" {
v.Set("userId", rjq.UserID)
}
if rjq.UserIDLiked != "" {
v.Set("userIdLiked", rjq.UserIDLiked)
}
if !rjq.FromDate.IsZero() {
v.Set("fromDate", rjq.FromDate.Format(FromDateFormat))
}
if rjq.Page != 0 {
v.Set("page", strconv.Itoa(rjq.Page))
}
if rjq.Prompt != "" {
v.Set("prompt", rjq.Prompt)
}
if rjq.Personal {
v.Set("personal", "true")
}
if rjq.Dedupe {
v.Set("dedupe", "true")
}
v.Set("refreshApi", strconv.Itoa(rjq.RefreshAPI))
return v
}
func (rjq *RecentJobsQuery) NextPage() *RecentJobsQuery {
q := *rjq
if q.OrderBy == OrderNew && q.FromDate.IsZero() {
q.FromDate = time.Now().UTC()
}
if q.Page == 0 {
q.Page = 1
}
q.Page = rjq.Page + 1
return &q
}
type RecentJobs struct {
Query RecentJobsQuery
Jobs []*Job
Page int
}
func (c *Client) RecentJobs(
ctx context.Context,
q *RecentJobsQuery,
) (*RecentJobs, error) {
u := &url.URL{
Path: "app/recent-jobs/",
RawQuery: q.Values().Encode(),
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
now := time.Now().UTC()
resp, err := c.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%w: %s", ErrResponseStatus, resp.Status)
}
rj := &RecentJobs{
Query: *q,
Jobs: []*Job{},
Page: q.Page,
}
err = json.NewDecoder(resp.Body).Decode(&rj.Jobs)
if err != nil {
return nil, err
}
if rj.Query.OrderBy == OrderNew && rj.Query.FromDate.IsZero() {
rj.Query.FromDate = now
}
return rj, nil
}
func (c *Client) Home(
ctx context.Context,
userID string,
) (*RecentJobs, error) {
if userID == "" {
return nil, ErrUserIDRequired
}
return c.RecentJobs(ctx, &RecentJobsQuery{
Amount: 50,
JobType: JobTypeNull,
OrderBy: OrderNew,
JobStatus: JobStatusCompleted,
UserID: userID,
Dedupe: true,
})
}
func (c *Client) CommunityFeed(ctx context.Context) (*RecentJobs, error) {
return c.RecentJobs(ctx, &RecentJobsQuery{
Amount: 50,
JobType: JobTypeUpscale,
OrderBy: OrderHot,
JobStatus: JobStatusCompleted,
Dedupe: true,
})
}
func (c *Client) PersonalFeed(ctx context.Context) (*RecentJobs, error) {
return c.RecentJobs(ctx, &RecentJobsQuery{
Amount: 50,
JobType: JobTypeUpscale,
OrderBy: OrderNew,
JobStatus: JobStatusCompleted,
Personal: true,
Dedupe: true,
})
}
func (c *Client) Bookmarks(
ctx context.Context,
userID string,
) (*RecentJobs, error) {
if userID == "" {
return nil, ErrUserIDRequired
}
return c.RecentJobs(ctx, &RecentJobsQuery{
Amount: 50,
JobType: JobTypeNull,
OrderBy: OrderLikedTime,
JobStatus: JobStatusCompleted,
UserIDLiked: userID,
Dedupe: true,
})
}