use chrono::{DateTime, Utc};
use chrono_tz::Tz;
use serde::Serialize;
use serde_with::{serde_as, DisplayFromStr};
use crate::{
request::{NoContent, TwitchAPIRequest},
schedule::ScheduleResponse,
types::{
constants::{
AFTER, BROADCASTER_ID, FIRST, ID, IS_VACATION_ENABLED, SCHEDULE, SEGMENT, SETTINGS,
START_TIME, TIMEZONE, VACATION_END_TIME, VACATION_START_TIME,
},
BroadcasterId, CategoryId, SegmentId,
},
TwitchAPI,
};
define_request_builder! {
#[derive(Debug)]
GetChanelStreamScheduleBuilder<'a> {
req: {broadcaster_id: &'a BroadcasterId [key = BROADCASTER_ID]},
opts: {
start_time: &'a DateTime<Utc> [key = START_TIME, convert = rfc3339_opt],
ids: &'a [&'a SegmentId] [key = ID, convert = extend],
first: u8 [key = FIRST, convert = to_string],
after: &'a str [key = AFTER]
}
} -> ScheduleResponse;
endpoint_type: GetChannelStreamSchedule,
method: GET,
path: [SCHEDULE],
}
define_request_builder! {
#[derive(Debug)]
UpdateChannelStreamScheduleBuilder<'a> {
req: {broadcaster_id: &'a BroadcasterId [key = BROADCASTER_ID]},
opts: {
vacation_start_time: &'a DateTime<Utc> [key = VACATION_START_TIME, convert = rfc3339_opt],
vacation_end_time: &'a DateTime<Utc> [key = VACATION_END_TIME, convert = rfc3339_opt],
timezone: Tz [key = TIMEZONE, convert = timezone],
is_vacation_enabled: bool [key = IS_VACATION_ENABLED, convert = to_string]
}
} -> NoContent;
endpoint_type: UpdateChannelStreamSchedule,
method: PATCH,
path: [SCHEDULE, SETTINGS],
}
#[serde_as]
#[derive(Debug, Serialize)]
pub struct CreateChannelStreamScheduleSegmentBuilder<'a> {
#[serde(skip)]
api: &'a TwitchAPI,
#[serde(skip)]
broadcaster_id: &'a BroadcasterId,
start_time: String,
timezone: &'a str,
#[serde_as(as = "DisplayFromStr")]
duration: u16,
#[serde(skip_serializing_if = "Option::is_none")]
category_id: Option<&'a CategoryId>,
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
is_recurring: Option<bool>,
}
impl<'a> CreateChannelStreamScheduleSegmentBuilder<'a> {
pub fn new(
api: &'a TwitchAPI,
broadcaster_id: &'a BroadcasterId,
start_time: &'a DateTime<Utc>,
timezone: Tz,
duration: u16,
) -> Self {
Self {
api,
broadcaster_id,
start_time: start_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
timezone: timezone.name(),
duration,
category_id: None,
title: None,
is_recurring: None,
}
}
opt_method!(category_id, &'a CategoryId);
opt_method!(title, &'a str);
opt_method!(is_recurring, bool);
pub fn build(self) -> TwitchAPIRequest<ScheduleResponse> {
let mut url = self.api.build_url();
url.path_segments_mut()
.unwrap()
.extend(&[SCHEDULE, SEGMENT]);
let mut query = url.query_pairs_mut();
query.append_pair(BROADCASTER_ID, self.broadcaster_id);
let body = serde_json::to_string(&self).ok();
drop(query);
TwitchAPIRequest::new(
crate::request::EndpointType::CreateChannelStreamScheduleSegment,
url,
reqwest::Method::POST,
self.api.header_json(),
body,
self.api.client.clone(),
)
}
pub async fn send(self) -> Result<reqwest::Response, crate::Error> {
self.build().send().await
}
pub async fn json(self) -> Result<ScheduleResponse, crate::Error> {
self.build().json().await
}
}
#[serde_as]
#[derive(Debug, Serialize)]
pub struct UpdateChannelStreamScheduleSegmentBulider<'a> {
#[serde(skip)]
api: &'a TwitchAPI,
#[serde(skip)]
broadcaster_id: &'a BroadcasterId,
#[serde(skip)]
id: &'a SegmentId,
#[serde(skip_serializing_if = "Option::is_none")]
start_time: Option<&'a str>,
#[serde_as(as = "Option<DisplayFromStr>")]
duration: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
category_id: Option<&'a CategoryId>,
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
timezone: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
is_canceled: Option<bool>,
}
impl<'a> UpdateChannelStreamScheduleSegmentBulider<'a> {
pub fn new(api: &'a TwitchAPI, broadcaster_id: &'a BroadcasterId, id: &'a SegmentId) -> Self {
Self {
api,
broadcaster_id,
id,
start_time: None,
duration: None,
category_id: None,
title: None,
timezone: None,
is_canceled: None,
}
}
opt_method!(start_time, &'a str);
opt_method!(duration, u16);
opt_method!(category_id, &'a CategoryId);
opt_method!(title, &'a str);
opt_method!(timezone, Tz[timezone]);
opt_method!(is_canceled, bool);
pub fn build(self) -> TwitchAPIRequest<ScheduleResponse> {
let mut url = self.api.build_url();
url.path_segments_mut()
.unwrap()
.extend(&[SCHEDULE, SEGMENT]);
let mut query = url.query_pairs_mut();
query.append_pair(BROADCASTER_ID, self.broadcaster_id);
query.append_pair(ID, self.id);
let body = serde_json::to_string(&self).ok();
drop(query);
TwitchAPIRequest::new(
crate::request::EndpointType::UpdateChannelStreamScheduleSegment,
url,
reqwest::Method::PATCH,
self.api.header_json(),
body,
self.api.client.clone(),
)
}
pub async fn send(self) -> Result<reqwest::Response, crate::Error> {
self.build().send().await
}
pub async fn json(self) -> Result<ScheduleResponse, crate::Error> {
self.build().json().await
}
}