213 lines
5.0 KiB
Go
213 lines
5.0 KiB
Go
package listing
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
ErrDependencyUnavailable = errors.New("dependency unavailable")
|
|
ErrInvalidInput = errors.New("invalid listing input")
|
|
ErrListingLocked = errors.New("listing locked")
|
|
ErrMissingTitle = errors.New("missing listing title")
|
|
ErrMissingServerRegion = errors.New("missing server region")
|
|
ErrInvalidPrice = errors.New("invalid listing price")
|
|
ErrInvalidDeposit = errors.New("invalid listing deposit")
|
|
ErrInvalidHafCoin = errors.New("invalid haf coin amount")
|
|
ErrMissingScreenshot = errors.New("missing screenshot")
|
|
)
|
|
|
|
type Service struct {
|
|
repo *Repository
|
|
config ConfigReader
|
|
}
|
|
|
|
type ConfigReader interface {
|
|
FindValue(key string) (string, error)
|
|
}
|
|
|
|
const reviewRequiredConfigKey = "listing.review_required"
|
|
|
|
func NewService(repo *Repository, config ConfigReader) *Service {
|
|
return &Service{repo: repo, config: config}
|
|
}
|
|
|
|
func (s *Service) Create(ownerID uint64, req CreateRequest) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if err := validateRequest(req); err != nil {
|
|
return nil, err
|
|
}
|
|
reviewRequired, err := s.reviewRequired()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.Create(ownerID, req, reviewRequired)
|
|
}
|
|
|
|
func (s *Service) Update(ownerID uint64, id uint64, req UpdateRequest) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if err := validateRequest(req); err != nil {
|
|
return nil, err
|
|
}
|
|
reviewRequired, err := s.reviewRequired()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.Update(ownerID, id, req, reviewRequired)
|
|
}
|
|
|
|
func (s *Service) SubmitReview(ownerID uint64, id uint64) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
reviewRequired, err := s.reviewRequired()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.SubmitReview(ownerID, id, reviewRequired)
|
|
}
|
|
|
|
func (s *Service) ListPendingReview() ([]ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListPendingReview()
|
|
}
|
|
|
|
func (s *Service) ListAdmin(query AdminListQuery) ([]ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListAdmin(query)
|
|
}
|
|
|
|
func (s *Service) FindAdmin(id uint64) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.FindAdmin(id)
|
|
}
|
|
|
|
func (s *Service) AdminOffline(adminID uint64, id uint64, req AdminActionRequest, meta AuditMeta) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Reason == "" {
|
|
return nil, ErrInvalidInput
|
|
}
|
|
return s.repo.AdminOffline(adminID, id, req, meta)
|
|
}
|
|
|
|
func (s *Service) AdminMarkAbnormal(adminID uint64, id uint64, req AdminActionRequest, meta AuditMeta) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Reason == "" {
|
|
return nil, ErrInvalidInput
|
|
}
|
|
return s.repo.AdminMarkAbnormal(adminID, id, req, meta)
|
|
}
|
|
|
|
func (s *Service) Approve(id uint64) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.Approve(id)
|
|
}
|
|
|
|
func (s *Service) Reject(id uint64, req ReviewRequest) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
if req.Reason == "" {
|
|
return nil, ErrInvalidInput
|
|
}
|
|
return s.repo.Reject(id, req)
|
|
}
|
|
|
|
func (s *Service) Offline(ownerID uint64, id uint64) error {
|
|
if s.repo == nil {
|
|
return ErrDependencyUnavailable
|
|
}
|
|
return s.repo.Offline(ownerID, id)
|
|
}
|
|
|
|
func (s *Service) ListPublic() ([]ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListPublic()
|
|
}
|
|
|
|
func (s *Service) ListMine(ownerID uint64) ([]ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.ListMine(ownerID)
|
|
}
|
|
|
|
func (s *Service) FindPublic(id uint64) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.FindPublic(id)
|
|
}
|
|
|
|
func (s *Service) FindMine(ownerID uint64, id uint64) (*ListingDTO, error) {
|
|
if s.repo == nil {
|
|
return nil, ErrDependencyUnavailable
|
|
}
|
|
return s.repo.FindMine(ownerID, id)
|
|
}
|
|
|
|
func validateRequest(req CreateRequest) error {
|
|
if strings.TrimSpace(req.Title) == "" {
|
|
return ErrMissingTitle
|
|
}
|
|
if strings.TrimSpace(req.ServerRegion) == "" {
|
|
return ErrMissingServerRegion
|
|
}
|
|
if req.PriceHourly <= 0 {
|
|
return ErrInvalidPrice
|
|
}
|
|
if req.DepositAmount < 0 {
|
|
return ErrInvalidDeposit
|
|
}
|
|
if req.HafCoinAmount < 0 {
|
|
return ErrInvalidHafCoin
|
|
}
|
|
if !hasScreenshotURL(req.ScreenshotURLS) {
|
|
return ErrMissingScreenshot
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func hasScreenshotURL(urls []string) bool {
|
|
for _, url := range urls {
|
|
if strings.TrimSpace(url) != "" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (s *Service) reviewRequired() (bool, error) {
|
|
if s.config == nil {
|
|
return false, nil
|
|
}
|
|
value, err := s.config.FindValue(reviewRequiredConfigKey)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
required, err := strconv.ParseBool(strings.TrimSpace(value))
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
return required, nil
|
|
}
|