use serde::{Deserialize, Serialize};
use crate::client::Notra;
use crate::error::Result;
use crate::models::{
ContentType, DataPoints, LookbackWindow, Organization, Pagination, Post, PostStatus,
Repository, SelectedItems, Sort,
};
#[derive(Debug, Deserialize)]
pub struct ListPostsResponse {
pub organization: Organization,
pub posts: Vec<Post>,
pub pagination: Pagination,
}
pub struct ListPostsBuilder<'a> {
client: &'a Notra,
sort: Option<Sort>,
limit: Option<u32>,
page: Option<u32>,
status: Option<PostStatus>,
content_type: Option<ContentType>,
}
impl<'a> ListPostsBuilder<'a> {
pub(crate) fn new(client: &'a Notra) -> Self {
Self {
client,
sort: None,
limit: None,
page: None,
status: None,
content_type: None,
}
}
pub fn sort(mut self, sort: Sort) -> Self {
self.sort = Some(sort);
self
}
pub fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
pub fn page(mut self, page: u32) -> Self {
self.page = Some(page);
self
}
pub fn status(mut self, status: PostStatus) -> Self {
self.status = Some(status);
self
}
pub fn content_type(mut self, content_type: ContentType) -> Self {
self.content_type = Some(content_type);
self
}
pub async fn send(self) -> Result<ListPostsResponse> {
let mut query: Vec<(&str, String)> = Vec::new();
if let Some(sort) = self.sort {
query.push(("sort", serde_json::to_value(sort).unwrap().as_str().unwrap().to_string()));
}
if let Some(limit) = self.limit {
query.push(("limit", limit.to_string()));
}
if let Some(page) = self.page {
query.push(("page", page.to_string()));
}
if let Some(status) = self.status {
query.push(("status", serde_json::to_value(status).unwrap().as_str().unwrap().to_string()));
}
if let Some(ct) = self.content_type {
query.push(("contentType", serde_json::to_value(ct).unwrap().as_str().unwrap().to_string()));
}
self.client.get("/v1/posts", &query).await
}
}
#[derive(Debug, Deserialize)]
pub struct GetPostResponse {
pub organization: Organization,
pub post: Option<Post>,
}
pub struct GetPostBuilder<'a> {
client: &'a Notra,
post_id: String,
}
impl<'a> GetPostBuilder<'a> {
pub(crate) fn new(client: &'a Notra, post_id: impl Into<String>) -> Self {
Self {
client,
post_id: post_id.into(),
}
}
pub async fn send(self) -> Result<GetPostResponse> {
let path = format!("/v1/posts/{}", self.post_id);
self.client.get(&path, &[]).await
}
}
#[derive(Debug, Deserialize)]
pub struct CreatePostGenerationResponse {
pub organization: Organization,
pub job: crate::models::PostGenerationJob,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct CreatePostGenerationBody {
content_type: ContentType,
#[serde(skip_serializing_if = "Option::is_none")]
lookback_window: Option<LookbackWindow>,
#[serde(skip_serializing_if = "Option::is_none")]
brand_voice_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
brand_identity_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
git_hub_integration_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
linear_integration_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
repositories: Option<Vec<Repository>>,
#[serde(skip_serializing_if = "Option::is_none")]
data_points: Option<DataPoints>,
#[serde(skip_serializing_if = "Option::is_none")]
selected_items: Option<SelectedItems>,
}
pub struct CreatePostGenerationBuilder<'a> {
client: &'a Notra,
content_type: ContentType,
lookback_window: Option<LookbackWindow>,
brand_voice_id: Option<String>,
brand_identity_id: Option<String>,
github_integration_ids: Option<Vec<String>>,
linear_integration_ids: Option<Vec<String>>,
repositories: Option<Vec<Repository>>,
data_points: Option<DataPoints>,
selected_items: Option<SelectedItems>,
}
impl<'a> CreatePostGenerationBuilder<'a> {
pub(crate) fn new(client: &'a Notra, content_type: ContentType) -> Self {
Self {
client,
content_type,
lookback_window: None,
brand_voice_id: None,
brand_identity_id: None,
github_integration_ids: None,
linear_integration_ids: None,
repositories: None,
data_points: None,
selected_items: None,
}
}
pub fn lookback_window(mut self, window: LookbackWindow) -> Self {
self.lookback_window = Some(window);
self
}
pub fn brand_voice_id(mut self, id: impl Into<String>) -> Self {
self.brand_voice_id = Some(id.into());
self
}
pub fn brand_identity_id(mut self, id: impl Into<String>) -> Self {
self.brand_identity_id = Some(id.into());
self
}
pub fn github_integration_ids(mut self, ids: Vec<String>) -> Self {
self.github_integration_ids = Some(ids);
self
}
pub fn linear_integration_ids(mut self, ids: Vec<String>) -> Self {
self.linear_integration_ids = Some(ids);
self
}
pub fn repositories(mut self, repos: Vec<Repository>) -> Self {
self.repositories = Some(repos);
self
}
pub fn data_points(mut self, data_points: DataPoints) -> Self {
self.data_points = Some(data_points);
self
}
pub fn selected_items(mut self, items: SelectedItems) -> Self {
self.selected_items = Some(items);
self
}
pub async fn send(self) -> Result<CreatePostGenerationResponse> {
let body = CreatePostGenerationBody {
content_type: self.content_type,
lookback_window: self.lookback_window,
brand_voice_id: self.brand_voice_id,
brand_identity_id: self.brand_identity_id,
git_hub_integration_ids: self.github_integration_ids,
linear_integration_ids: self.linear_integration_ids,
repositories: self.repositories,
data_points: self.data_points,
selected_items: self.selected_items,
};
self.client.post("/v1/posts/generate", &body).await
}
}
#[derive(Debug, Deserialize)]
pub struct GetPostGenerationResponse {
pub organization: Organization,
pub job: crate::models::PostGenerationJob,
#[serde(default)]
pub events: Vec<crate::models::JobEvent>,
}
pub struct GetPostGenerationBuilder<'a> {
client: &'a Notra,
job_id: String,
}
impl<'a> GetPostGenerationBuilder<'a> {
pub(crate) fn new(client: &'a Notra, job_id: impl Into<String>) -> Self {
Self {
client,
job_id: job_id.into(),
}
}
pub async fn send(self) -> Result<GetPostGenerationResponse> {
let path = format!("/v1/posts/generate/{}", self.job_id);
self.client.get(&path, &[]).await
}
}
#[derive(Debug, Deserialize)]
pub struct UpdatePostResponse {
pub organization: Organization,
pub post: Post,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct UpdatePostBody {
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
slug: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
markdown: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
status: Option<PostStatus>,
}
pub struct UpdatePostBuilder<'a> {
client: &'a Notra,
post_id: String,
title: Option<String>,
slug: Option<String>,
markdown: Option<String>,
status: Option<PostStatus>,
}
impl<'a> UpdatePostBuilder<'a> {
pub(crate) fn new(client: &'a Notra, post_id: impl Into<String>) -> Self {
Self {
client,
post_id: post_id.into(),
title: None,
slug: None,
markdown: None,
status: None,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn slug(mut self, slug: impl Into<String>) -> Self {
self.slug = Some(slug.into());
self
}
pub fn markdown(mut self, markdown: impl Into<String>) -> Self {
self.markdown = Some(markdown.into());
self
}
pub fn status(mut self, status: PostStatus) -> Self {
self.status = Some(status);
self
}
pub async fn send(self) -> Result<UpdatePostResponse> {
let path = format!("/v1/posts/{}", self.post_id);
let body = UpdatePostBody {
title: self.title,
slug: self.slug,
markdown: self.markdown,
status: self.status,
};
self.client.patch(&path, &body).await
}
}
#[derive(Debug, Deserialize)]
pub struct DeletePostResponse {
pub id: String,
pub organization: Organization,
}
pub struct DeletePostBuilder<'a> {
client: &'a Notra,
post_id: String,
}
impl<'a> DeletePostBuilder<'a> {
pub(crate) fn new(client: &'a Notra, post_id: impl Into<String>) -> Self {
Self {
client,
post_id: post_id.into(),
}
}
pub async fn send(self) -> Result<DeletePostResponse> {
let path = format!("/v1/posts/{}", self.post_id);
self.client.delete(&path).await
}
}