lure/cmd/lure-api/api.go

158 lines
3.8 KiB
Go

package main
import (
"context"
"fmt"
"strconv"
"time"
"github.com/genjidb/genji"
"github.com/genjidb/genji/document"
"github.com/genjidb/genji/types"
"go.arsenm.dev/lure/cmd/lure-api/internal/api"
"go.arsenm.dev/lure/internal/db"
)
type lureWebAPI struct {
db *genji.DB
}
func (l lureWebAPI) CreateComment(ctx context.Context, req *api.CreateCommentRequest) (*api.CreateCommentResponse, error) {
count, err := db.CountComments(l.db)
if err != nil {
return nil, err
}
err = db.InsertComment(l.db, db.Comment{
CommentID: count,
PackageName: req.PkgName,
PackageRepo: req.Repository,
TimeCreated: time.Now().Unix(),
Contents: req.Contents,
})
if err != nil {
return nil, err
}
return &api.CreateCommentResponse{CommentId: count}, nil
}
func (l lureWebAPI) EditComment(ctx context.Context, req *api.EditCommentRequest) (*api.EmptyResponse, error) {
doc, err := db.GetComment(l.db, "comment_id = ?", req.CommentId)
if err != nil {
return nil, err
}
var comment db.Comment
err = document.ScanDocument(doc, &comment)
if err != nil {
return nil, err
}
comment.Contents = req.NewContents
err = db.InsertComment(l.db, comment)
return &api.EmptyResponse{}, err
}
func (l lureWebAPI) GetComments(ctx context.Context, req *api.GetCommentsRequest) (*api.GetCommentsResponse, error) {
doc, err := db.GetComments(
l.db,
"package_repo = ? AND package_name = ? AND time_created >= ? LIMIT ?",
req.PkgName,
req.Repository,
req.CreatedSince,
req.Limit,
)
if err != nil {
return nil, err
}
out := &api.GetCommentsResponse{}
err = doc.Iterate(func(d types.Document) error {
comment := &api.Comment{}
err = document.ScanDocument(d, comment)
if err != nil {
return err
}
out.Comments = append(out.Comments, comment)
return nil
})
return out, err
}
func (l lureWebAPI) Search(ctx context.Context, req *api.SearchRequest) (*api.SearchResponse, error) {
query := "(name LIKE ? OR description LIKE ? OR ? IN provides)"
args := []any{"%" + req.Query + "%", "%" + req.Query + "%", req.Query}
if req.FilterValue != nil && req.FilterType != api.FILTER_TYPE_NO_FILTER {
switch req.FilterType {
case api.FILTER_TYPE_IN_REPOSITORY:
query += " AND repository = ?"
case api.FILTER_TYPE_SUPPORTS_ARCH:
query += " AND ? IN architectures"
}
args = append(args, *req.FilterValue)
}
if req.SortBy != api.SORT_BY_UNSORTED {
switch req.SortBy {
case api.SORT_BY_NAME:
query += " ORDER BY name"
case api.SORT_BY_REPOSITORY:
query += " ORDER BY repository"
case api.SORT_BY_VERSION:
query += " ORDER BY version"
}
}
if req.Limit != 0 {
query += " LIMIT " + strconv.FormatInt(req.Limit, 10)
}
doc, err := db.GetPkgs(l.db, query, args...)
if err != nil {
return nil, err
}
fmt.Println(query, args)
out := &api.SearchResponse{}
err = doc.Iterate(func(d types.Document) error {
pkg := &db.Package{}
err = document.ScanDocument(d, pkg)
if err != nil {
return err
}
out.Packages = append(out.Packages, &api.Package{
Name: pkg.Name,
Repository: pkg.Repository,
Version: pkg.Version,
Release: int64(pkg.Release),
Epoch: ptr(int64(pkg.Epoch)),
Description: &pkg.Description,
Homepage: &pkg.Homepage,
Maintainer: &pkg.Maintainer,
Architectures: pkg.Architectures,
Licenses: pkg.Licenses,
Provides: pkg.Provides,
Conflicts: pkg.Conflicts,
Replaces: pkg.Replaces,
Depends: dbMapToAPI(pkg.Depends),
BuildDepends: dbMapToAPI(pkg.BuildDepends),
})
return nil
})
return out, err
}
func ptr[T any](v T) *T {
return &v
}
func dbMapToAPI(m map[string][]string) map[string]*api.StringList {
out := make(map[string]*api.StringList, len(m))
for override, list := range m {
out[override] = &api.StringList{Entries: list}
}
return out
}