Clone the twdehands SDK into mrktplaats and retarget naming and defaults for app.marktplaats.nl while keeping the same request/response bodies and endpoint behavior.
187 lines
6.2 KiB
Go
187 lines
6.2 KiB
Go
package mrktplaats
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Price represents a listing price. All amounts are in euro cents.
|
|
type Price struct {
|
|
PriceType string `json:"priceType"`
|
|
PriceTypeLabel string `json:"priceTypeLabel"`
|
|
PriceAmount int `json:"priceAmount"`
|
|
}
|
|
|
|
// Picture represents an image with CDN URLs at various sizes.
|
|
type Picture struct {
|
|
ID int `json:"id"`
|
|
ExtraSmall string `json:"extraSmall"`
|
|
Medium string `json:"medium"`
|
|
Large string `json:"large"`
|
|
ExtraExtraLarge string `json:"extraExtraLarge,omitempty"`
|
|
AspectRatio interface{} `json:"aspectRatio,omitempty"`
|
|
Width int `json:"width,omitempty"`
|
|
Height int `json:"height,omitempty"`
|
|
}
|
|
|
|
// AdAddress represents the geographic location of a listing.
|
|
type AdAddress struct {
|
|
City string `json:"city"`
|
|
Country string `json:"country"`
|
|
CountryAbbreviation string `json:"countryAbbreviation"`
|
|
ZipCode string `json:"zipCode,omitempty"`
|
|
Latitude float64 `json:"latitude"`
|
|
Longitude float64 `json:"longitude"`
|
|
}
|
|
|
|
// Attribute represents a listing attribute (e.g. condition, brand).
|
|
type Attribute struct {
|
|
ID int `json:"id"`
|
|
Key string `json:"key"`
|
|
Name string `json:"name"`
|
|
Values []AttributeValue `json:"values"`
|
|
}
|
|
|
|
// AttributeValue represents a single value of an attribute.
|
|
type AttributeValue struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
// AdCore contains the core fields shared across search results and item detail views.
|
|
type AdCore struct {
|
|
URN string `json:"urn"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description,omitempty"`
|
|
CategoryID int `json:"categoryId"`
|
|
Price Price `json:"price"`
|
|
Picture *Picture `json:"picture,omitempty"`
|
|
Pictures []Picture `json:"pictures,omitempty"`
|
|
AdAddress AdAddress `json:"adAddress"`
|
|
Attributes []Attribute `json:"attributes,omitempty"`
|
|
Link string `json:"link,omitempty"`
|
|
}
|
|
|
|
// SellerInformation identifies the seller of a listing.
|
|
type SellerInformation struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type,omitempty"`
|
|
Phone string `json:"phone,omitempty"`
|
|
PhoneHidden bool `json:"phoneNumberHidden,omitempty"`
|
|
AllowASQ bool `json:"allowAsq,omitempty"`
|
|
ActiveSince json.RawMessage `json:"activeSince,omitempty"`
|
|
SavedForUser bool `json:"savedForUser,omitempty"`
|
|
KYCState json.RawMessage `json:"kycState,omitempty"`
|
|
MerchantState string `json:"merchantState,omitempty"`
|
|
DealerPackage string `json:"dealerPackage,omitempty"`
|
|
}
|
|
|
|
// User represents an authenticated user account.
|
|
type User struct {
|
|
ID int `json:"id"`
|
|
EncryptedID string `json:"encryptedId"`
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
Phone string `json:"phone"`
|
|
ZipCode string `json:"zipCode"`
|
|
ActivationDate string `json:"activationDate"`
|
|
RegistrationDate string `json:"registrationDate"`
|
|
OneClickOptedIn bool `json:"oneClickOptedIn"`
|
|
OneClickBlocked bool `json:"oneClickBlocked"`
|
|
ProfilePicture string `json:"profilePicture"`
|
|
ShowMapOnVipEnabled bool `json:"showMapOnVipEnabled"`
|
|
NdfcDeclarationStatus string `json:"ndfcDeclarationStatus"`
|
|
}
|
|
|
|
// DiscoveryPrice is the snake_case price used by older API3 endpoints.
|
|
type DiscoveryPrice struct {
|
|
PriceType string `json:"price_type"`
|
|
PriceTypeLabel string `json:"price_type_label"`
|
|
PriceAmount int `json:"price_amount"`
|
|
}
|
|
|
|
// DiscoveryPicture is the snake_case picture used by older API3 endpoints.
|
|
type DiscoveryPicture struct {
|
|
ID int `json:"id"`
|
|
ExtraSmall string `json:"extra_small"`
|
|
Medium string `json:"medium"`
|
|
Large string `json:"large"`
|
|
}
|
|
|
|
// FlexTime is a time.Time that accepts dates without a timezone suffix
|
|
// (e.g. "2025-10-18T14:50:53") in addition to standard RFC3339.
|
|
type FlexTime struct{ time.Time }
|
|
|
|
// UnmarshalJSON parses RFC3339 dates, falling back to local (UTC) parsing
|
|
// when the timezone suffix is absent.
|
|
func (ft *FlexTime) UnmarshalJSON(data []byte) error {
|
|
if len(data) < 2 || data[0] != '"' {
|
|
return nil
|
|
}
|
|
s := string(data[1 : len(data)-1])
|
|
t, err := time.Parse(time.RFC3339, s)
|
|
if err != nil {
|
|
t, err = time.ParseInLocation("2006-01-02T15:04:05", s, time.UTC)
|
|
if err != nil {
|
|
return fmt.Errorf("FlexTime: cannot parse %q", s)
|
|
}
|
|
}
|
|
ft.Time = t
|
|
return nil
|
|
}
|
|
|
|
// Review represents a user review.
|
|
type Review struct {
|
|
ID int `json:"id"`
|
|
Reviewer ReviewUser `json:"reviewer"`
|
|
Reviewee ReviewUser `json:"reviewee"`
|
|
Direction string `json:"direction"`
|
|
CreationDate FlexTime `json:"creationDate"`
|
|
Score int `json:"score"`
|
|
ItemID string `json:"itemId"`
|
|
Advertisement ReviewAd `json:"advertisement"`
|
|
Details []ReviewDetail `json:"details"`
|
|
Content ReviewContent `json:"content"`
|
|
ReviewSubject string `json:"reviewSubject"`
|
|
}
|
|
|
|
// ReviewUser is a participant in a review.
|
|
type ReviewUser struct {
|
|
ID int `json:"id"`
|
|
Nickname string `json:"nickname"`
|
|
}
|
|
|
|
// ReviewAd is the listing associated with a review.
|
|
type ReviewAd struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
CategoryName string `json:"categoryName"`
|
|
}
|
|
|
|
// ReviewDetail contains category-level review scoring.
|
|
type ReviewDetail struct {
|
|
Category string `json:"category"`
|
|
Score int `json:"score"`
|
|
Characteristics []ReviewCharacteristic `json:"characteristics"`
|
|
}
|
|
|
|
// ReviewCharacteristic is an individual review trait.
|
|
type ReviewCharacteristic struct {
|
|
ID int `json:"id"`
|
|
Text string `json:"text"`
|
|
IsPositive bool `json:"isPositive"`
|
|
}
|
|
|
|
// ReviewContent holds the textual content of a review.
|
|
type ReviewContent struct {
|
|
Subject string `json:"subject"`
|
|
}
|
|
|
|
// ReviewSummary provides aggregate review statistics.
|
|
type ReviewSummary struct {
|
|
NumberOfReviews int `json:"numberOfReviews"`
|
|
AverageScore float64 `json:"averageScore"`
|
|
}
|