207 lines
5.5 KiB
C#
207 lines
5.5 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace Creative.Models;
|
|
|
|
// ============================================================
|
|
// Request / Response envelope (matches ProviderModels pattern)
|
|
// ============================================================
|
|
|
|
/// <summary>
|
|
/// Inbound request from Gateway via /internal/execute.
|
|
/// </summary>
|
|
public class CreativeRequest
|
|
{
|
|
[JsonPropertyName("operation")]
|
|
public string? Operation { get; set; }
|
|
|
|
[JsonPropertyName("requestId")]
|
|
public string? RequestId { get; set; }
|
|
|
|
[JsonPropertyName("payload")]
|
|
public Dictionary<string, object>? Payload { get; set; }
|
|
|
|
// Session context forwarded by Gateway
|
|
[JsonPropertyName("session")]
|
|
public SessionContext? Session { get; set; }
|
|
}
|
|
|
|
public class SessionContext
|
|
{
|
|
[JsonPropertyName("sessionId")]
|
|
public string? SessionId { get; set; }
|
|
|
|
[JsonPropertyName("clientId")]
|
|
public string? ClientId { get; set; }
|
|
|
|
[JsonPropertyName("clientName")]
|
|
public string? ClientName { get; set; }
|
|
|
|
[JsonPropertyName("userId")]
|
|
public string? UserId { get; set; }
|
|
|
|
[JsonPropertyName("userEmail")]
|
|
public string? UserEmail { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Standard response envelope.
|
|
/// </summary>
|
|
public class CreativeResponse
|
|
{
|
|
[JsonPropertyName("ok")]
|
|
public bool Ok { get; set; }
|
|
|
|
[JsonPropertyName("requestId")]
|
|
public string? RequestId { get; set; }
|
|
|
|
[JsonPropertyName("data")]
|
|
public object? Data { get; set; }
|
|
|
|
[JsonPropertyName("error")]
|
|
public object? Error { get; set; }
|
|
|
|
public static CreativeResponse Success(string requestId, object? data = null) => new()
|
|
{
|
|
Ok = true,
|
|
RequestId = requestId,
|
|
Data = data
|
|
};
|
|
|
|
public static CreativeResponse Fail(string requestId, string code, string message, object? details = null) => new()
|
|
{
|
|
Ok = false,
|
|
RequestId = requestId,
|
|
Error = new { code, message, details }
|
|
};
|
|
}
|
|
|
|
// ============================================================
|
|
// Domain models - scraped content and generated assets
|
|
// ============================================================
|
|
|
|
/// <summary>
|
|
/// Result of scraping and analyzing a URL.
|
|
/// </summary>
|
|
public class UrlAnalysis
|
|
{
|
|
[JsonPropertyName("url")]
|
|
public string Url { get; set; } = "";
|
|
|
|
[JsonPropertyName("title")]
|
|
public string? Title { get; set; }
|
|
|
|
[JsonPropertyName("metaDescription")]
|
|
public string? MetaDescription { get; set; }
|
|
|
|
[JsonPropertyName("headings")]
|
|
public List<string> Headings { get; set; } = new();
|
|
|
|
[JsonPropertyName("bodySnippet")]
|
|
public string? BodySnippet { get; set; }
|
|
|
|
[JsonPropertyName("inferredCategory")]
|
|
public string? InferredCategory { get; set; }
|
|
|
|
[JsonPropertyName("scrapedAt")]
|
|
public DateTimeOffset ScrapedAt { get; set; } = DateTimeOffset.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A single text asset (headline or description) for Google Ads.
|
|
/// </summary>
|
|
public class TextAsset
|
|
{
|
|
[JsonPropertyName("type")]
|
|
public string Type { get; set; } = ""; // "headline" or "description"
|
|
|
|
[JsonPropertyName("text")]
|
|
public string Text { get; set; } = "";
|
|
|
|
[JsonPropertyName("charCount")]
|
|
public int CharCount { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// An image asset sourced for the campaign.
|
|
/// </summary>
|
|
public class ImageAsset
|
|
{
|
|
[JsonPropertyName("imageId")]
|
|
public string ImageId { get; set; } = "";
|
|
|
|
[JsonPropertyName("url")]
|
|
public string Url { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Where the image came from: "emulated" | "unsplash" | "dalle"
|
|
/// </summary>
|
|
[JsonPropertyName("source")]
|
|
public string Source { get; set; } = "emulated";
|
|
|
|
/// <summary>
|
|
/// Orientation/aspect: "landscape" | "square" | "portrait"
|
|
/// </summary>
|
|
[JsonPropertyName("orientation")]
|
|
public string Orientation { get; set; } = "landscape";
|
|
|
|
[JsonPropertyName("width")]
|
|
public int Width { get; set; }
|
|
|
|
[JsonPropertyName("height")]
|
|
public int Height { get; set; }
|
|
|
|
[JsonPropertyName("altText")]
|
|
public string? AltText { get; set; }
|
|
|
|
/// <summary>
|
|
/// Attribution line (required by Unsplash TOS, informational for others).
|
|
/// </summary>
|
|
[JsonPropertyName("attribution")]
|
|
public string? Attribution { get; set; }
|
|
|
|
/// <summary>
|
|
/// Direct download/full-res URL if different from display URL.
|
|
/// </summary>
|
|
[JsonPropertyName("downloadUrl")]
|
|
public string? DownloadUrl { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Complete set of generated assets for a campaign draft.
|
|
/// </summary>
|
|
public class CampaignDraft
|
|
{
|
|
[JsonPropertyName("draftId")]
|
|
public string DraftId { get; set; } = "";
|
|
|
|
[JsonPropertyName("url")]
|
|
public string Url { get; set; } = "";
|
|
|
|
[JsonPropertyName("analysis")]
|
|
public UrlAnalysis? Analysis { get; set; }
|
|
|
|
[JsonPropertyName("headlines")]
|
|
public List<TextAsset> Headlines { get; set; } = new();
|
|
|
|
[JsonPropertyName("descriptions")]
|
|
public List<TextAsset> Descriptions { get; set; } = new();
|
|
|
|
[JsonPropertyName("images")]
|
|
public List<ImageAsset> Images { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// Copy source: "emulated" | "openai"
|
|
/// </summary>
|
|
[JsonPropertyName("source")]
|
|
public string Source { get; set; } = "emulated";
|
|
|
|
/// <summary>
|
|
/// Image source: "emulated" | "unsplash" | "dalle"
|
|
/// </summary>
|
|
[JsonPropertyName("imageSource")]
|
|
public string ImageSource { get; set; } = "emulated";
|
|
|
|
[JsonPropertyName("createdAt")]
|
|
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
|
}
|