This commit is contained in:
Artem Tsyrulnikov
2026-01-19 12:50:36 +03:00
parent 62e8f98429
commit 5473b26787
17 changed files with 478 additions and 599 deletions

View File

@@ -532,65 +532,90 @@ func (c *Client) DeleteCreative(
}
// ============================================================================
// Placements (Размещения/Закупы)
// Placements (Размещения)
// ============================================================================
type Placement struct {
ID string `json:"id"`
ProjectID string `json:"project_id"`
ProjectChannelTitle *string `json:"project_channel_title"`
PlacementChannelID string `json:"placement_channel_id"`
PlacementChannelTitle *string `json:"placement_channel_title"`
CreativeID string `json:"creative_id"`
CreativeName string `json:"creative_name"`
PlacementDate string `json:"placement_date"`
Cost *float64 `json:"cost"`
Comment *string `json:"comment"`
AdPostURL *string `json:"ad_post_url"`
InviteLinkType string `json:"invite_link_type"`
InviteLink string `json:"invite_link"`
Status string `json:"status"`
SubscriptionsCount int `json:"subscriptions_count"`
PurchaseID *string `json:"purchase_id"`
PurchaseChannelID *string `json:"purchase_channel_id"`
CreatedAt string `json:"created_at"`
type Channel struct {
ID string `json:"id"`
TelegramID *int64 `json:"telegram_id"`
Title *string `json:"title"`
Username *string `json:"username"`
}
type PlacementsPage struct {
Items []Placement `json:"items"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
Pages int `json:"pages"`
type CostInfo struct {
Type string `json:"type"`
Value float64 `json:"value"`
}
type PlacementDetails struct {
PlacementAt *string `json:"placement_at,omitempty"`
PaymentAt *string `json:"payment_at,omitempty"`
Cost *CostInfo `json:"cost,omitempty"`
CostBeforeBargain *float64 `json:"cost_before_bargain,omitempty"`
PlacementType *string `json:"placement_type,omitempty"`
Format *string `json:"format,omitempty"`
Comment *string `json:"comment,omitempty"`
}
type PlacementOutput struct {
ID string `json:"id"`
Status string `json:"status"`
Comment *string `json:"comment,omitempty"`
InviteLink string `json:"invite_link"`
InviteLinkType string `json:"invite_link_type"`
Channel Channel `json:"channel"`
Details *PlacementDetails `json:"details,omitempty"`
}
type CreatePlacementChannelInput struct {
Username string `json:"username"`
Status *string `json:"status,omitempty"`
Comment *string `json:"comment,omitempty"`
Details *PlacementDetails `json:"details,omitempty"`
}
type CreatePlacementsInput struct {
CreativeID string `json:"creative_id"`
Channels []CreatePlacementChannelInput `json:"channels"`
Details *PlacementDetails `json:"details,omitempty"`
}
type GetPlacementsOutput struct {
Placements []PlacementOutput `json:"placements"`
}
func (c *Client) CreatePlacements(
ctx context.Context,
jwt string,
workspaceID string,
projectID string,
input CreatePlacementsInput,
) (*GetPlacementsOutput, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/placements", workspaceID, projectID)
var placements GetPlacementsOutput
err := c.do(
ctx,
http.MethodPost,
path,
input,
&placements,
withBearer(jwt),
)
return &placements, err
}
func (c *Client) GetPlacements(
ctx context.Context,
jwt string,
workspaceID string,
projectID *string,
placementChannelID *string,
creativeID *string,
includeArchived bool,
page, size int,
) (*PlacementsPage, error) {
q := url.Values{}
if projectID != nil {
q.Set("project_id", *projectID)
}
if placementChannelID != nil {
q.Set("placement_channel_id", *placementChannelID)
}
if creativeID != nil {
q.Set("creative_id", *creativeID)
}
q.Set("include_archived", fmt.Sprint(includeArchived))
q.Set("page", fmt.Sprint(page))
q.Set("size", fmt.Sprint(size))
projectID string,
) (*GetPlacementsOutput, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/placements", workspaceID, projectID)
path := fmt.Sprintf("api/v1/workspaces/%s/placements?%s", workspaceID, q.Encode())
var resp GetPlacementsOutput
var resp PlacementsPage
err := c.do(
ctx,
http.MethodGet,
@@ -607,11 +632,12 @@ func (c *Client) GetPlacement(
ctx context.Context,
jwt string,
workspaceID string,
projectID string,
placementID string,
) (*Placement, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/placements/%s", workspaceID, placementID)
) (*PlacementOutput, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/placements/%s", workspaceID, projectID, placementID)
var placement Placement
var placement PlacementOutput
err := c.do(
ctx,
http.MethodGet,
@@ -624,140 +650,6 @@ func (c *Client) GetPlacement(
return &placement, err
}
// Note: Placement creation/updates are handled by worker; API exposes only read endpoints.
// ============================================================================
// Purchases (Закупы)
// ============================================================================
type Channel struct {
ID string `json:"id"`
TelegramID *int64 `json:"telegram_id"`
Title *string `json:"title"`
Username *string `json:"username"`
}
type Purchase struct {
ID string `json:"id"`
Status string `json:"status"`
CreativeID string `json:"creative_id"`
Channels []PurchaseChannelOut `json:"channels"`
Details *PurchaseDetails `json:"details,omitempty"`
}
type PurchaseChannelOut struct {
ID string `json:"id"`
Status string `json:"status"`
Comment *string `json:"comment"`
InviteLink string `json:"invite_link"`
InviteLinkType string `json:"invite_link_type"`
Channel Channel `json:"channel"`
Details *PurchaseChannelDetails `json:"details,omitempty"`
}
type CostInfo struct {
Type string `json:"type"`
Value float64 `json:"value"`
}
type PurchaseDetails struct {
PlacementAt *string `json:"placement_at,omitempty"`
PaymentAt *string `json:"payment_at,omitempty"`
Cost *CostInfo `json:"cost,omitempty"`
CostBeforeBargain *float64 `json:"cost_before_bargain,omitempty"`
PurchaseType *string `json:"purchase_type,omitempty"`
Format *string `json:"format,omitempty"`
Comment *string `json:"comment,omitempty"`
}
type PurchaseChannelDetails struct {
PlacementAt *string `json:"placement_at,omitempty"`
Cost *CostInfo `json:"cost,omitempty"`
CostBeforeBargain *float64 `json:"cost_before_bargain,omitempty"`
Format *string `json:"format,omitempty"`
}
type CreatePurchaseChannelInput struct {
Username string `json:"username"`
Status *string `json:"status,omitempty"`
Comment *string `json:"comment,omitempty"`
Details *PurchaseChannelDetails `json:"details,omitempty"`
}
type CreatePurchaseInput struct {
CreativeID string `json:"creative_id"`
Channels []CreatePurchaseChannelInput `json:"channels"`
Details *PurchaseDetails `json:"details,omitempty"`
}
func (c *Client) CreatePurchase(
ctx context.Context,
jwt string,
workspaceID string,
projectID string,
input CreatePurchaseInput,
) (*Purchase, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/purchase", workspaceID, projectID)
var purchase Purchase
err := c.do(
ctx,
http.MethodPost,
path,
input,
&purchase,
withBearer(jwt),
)
return &purchase, err
}
func (c *Client) GetPurchases(
ctx context.Context,
jwt string,
workspaceID string,
projectID string,
) ([]Purchase, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/purchase", workspaceID, projectID)
var resp struct {
Items []Purchase `json:"items"`
}
err := c.do(
ctx,
http.MethodGet,
path,
nil,
&resp,
withBearer(jwt),
)
return resp.Items, err
}
func (c *Client) GetPurchase(
ctx context.Context,
jwt string,
workspaceID string,
projectID string,
purchaseID string,
) (*Purchase, error) {
path := fmt.Sprintf("api/v1/workspaces/%s/projects/%s/purchase/%s", workspaceID, projectID, purchaseID)
var purchase Purchase
err := c.do(
ctx,
http.MethodGet,
path,
nil,
&purchase,
withBearer(jwt),
)
return &purchase, err
}
// ============================================================================
// Workspace Members
// ============================================================================