Initial Marktplaats SDK scaffold
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.
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
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"`
|
||||
}
|
||||
Reference in New Issue
Block a user