This commit is contained in:
Artem Tsyrulnikov
2026-01-19 13:04:30 +03:00
parent 5473b26787
commit 72856aaf77
8 changed files with 111 additions and 1 deletions

View File

@@ -567,6 +567,16 @@ type PlacementOutput struct {
Details *PlacementDetails `json:"details,omitempty"`
}
type PlacementPostOutput struct {
ID string `json:"id"`
PlacementID string `json:"placement_id"`
Placement PlacementOutput `json:"placement"`
AdPostURL *string `json:"ad_post_url,omitempty"`
Status string `json:"status"`
SubscriptionsCount int `json:"subscriptions_count"`
CreatedAt string `json:"created_at"`
}
type CreatePlacementChannelInput struct {
Username string `json:"username"`
Status *string `json:"status,omitempty"`
@@ -584,6 +594,10 @@ type GetPlacementsOutput struct {
Placements []PlacementOutput `json:"placements"`
}
type GetPlacementPostsOutput struct {
PlacementPosts []PlacementPostOutput `json:"placement_posts"`
}
func (c *Client) CreatePlacements(
ctx context.Context,
jwt string,
@@ -650,6 +664,39 @@ func (c *Client) GetPlacement(
return &placement, err
}
func (c *Client) GetPlacementPosts(
ctx context.Context,
jwt string,
workspaceID string,
projectID *string,
placementID *string,
) (*GetPlacementPostsOutput, error) {
q := url.Values{}
if projectID != nil && *projectID != "" {
q.Set("project_id", *projectID)
}
if placementID != nil && *placementID != "" {
q.Set("placement_id", *placementID)
}
path := fmt.Sprintf("api/v1/workspaces/%s/placement_posts", workspaceID)
if len(q) > 0 {
path += "?" + q.Encode()
}
var resp GetPlacementPostsOutput
err := c.do(
ctx,
http.MethodGet,
path,
nil,
&resp,
withBearer(jwt),
)
return &resp, err
}
// ============================================================================
// Workspace Members
// ============================================================================

View File

@@ -44,6 +44,28 @@ func (s *PlacementDetails) renderDetails(b *bot.Bot, mode bot.RenderMode, jwt st
return
}
placementPosts, err := b.Backend.GetPlacementPosts(
context.Background(),
jwt,
s.WorkspaceID,
&s.ProjectID,
&s.PlacementID,
)
if err != nil {
log.Error().Err(err).Msg("Failed to get placement posts")
}
var placementPost *backend.PlacementPostOutput
if placementPosts != nil {
for i := range placementPosts.PlacementPosts {
post := &placementPosts.PlacementPosts[i]
if post.PlacementID == s.PlacementID {
placementPost = post
break
}
}
}
text := "<b>Детали размещения</b>\n\n"
channelName := formatChannelName(placement.Channel)
@@ -78,6 +100,16 @@ func (s *PlacementDetails) renderDetails(b *bot.Bot, mode bot.RenderMode, jwt st
}
}
if placementPost != nil {
text += "\n<b>Пост</b>\n"
if placementPost.AdPostURL != nil && *placementPost.AdPostURL != "" {
text += fmt.Sprintf("• <b>Ссылка на пост:</b> %s\n", *placementPost.AdPostURL)
} else {
text += "• <b>Ссылка на пост:</b> не найдена\n"
}
text += fmt.Sprintf("• <b>Статус поста:</b> %s\n", formatPlacementPostStatus(placementPost.Status))
}
keyboard := Keyboard(Row(Button("← Назад", "back")))
b.Render(text, keyboard, mode)
}
@@ -129,6 +161,18 @@ func formatPlacementType(value string) string {
}
}
func formatPlacementPostStatus(status string) string {
normalized := strings.TrimSpace(strings.ToLower(status))
switch normalized {
case "active":
return "Активен"
case "archived":
return "Архивирован"
default:
return status
}
}
func formatCostType(value string) string {
switch strings.TrimSpace(strings.ToLower(value)) {
case "cpm":