use crate::models::billing::{
ActionsBillingUsage, BillingAiCreditUsageReport, BillingPremiumRequestUsageReport,
BillingUsageReport, BillingUsageSummaryReport, Budget, CombinedBillingUsage, CreateBudget,
CreateBudgetResponse, DeleteBudgetResponse, GetAllBudgets, PackagesBillingUsage, UpdateBudget,
UpdateBudgetResponse,
};
use crate::{Octocrab, Result};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BillingOwner {
Org(String),
User(String),
}
impl BillingOwner {
pub(crate) fn legacy_prefix(&self) -> String {
match self {
Self::Org(org) => format!("/orgs/{org}/settings/billing"),
Self::User(user) => format!("/users/{user}/settings/billing"),
}
}
pub(crate) fn usage_prefix(&self) -> String {
match self {
Self::Org(org) => format!("/organizations/{org}/settings/billing"),
Self::User(user) => format!("/users/{user}/settings/billing"),
}
}
}
pub struct BillingHandler<'octo> {
crab: &'octo Octocrab,
}
impl<'octo> BillingHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab) -> Self {
Self { crab }
}
pub fn org(&self, org: impl Into<String>) -> ScopedBillingHandler<'octo> {
ScopedBillingHandler::new(self.crab, BillingOwner::Org(org.into()))
}
pub fn user(&self, user: impl Into<String>) -> ScopedBillingHandler<'octo> {
ScopedBillingHandler::new(self.crab, BillingOwner::User(user.into()))
}
}
pub struct ScopedBillingHandler<'octo> {
crab: &'octo Octocrab,
owner: BillingOwner,
}
impl<'octo> ScopedBillingHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab, owner: BillingOwner) -> Self {
Self { crab, owner }
}
pub fn org(&self, org: impl Into<String>) -> Self {
Self::new(self.crab, BillingOwner::Org(org.into()))
}
pub fn user(&self, user: impl Into<String>) -> Self {
Self::new(self.crab, BillingOwner::User(user.into()))
}
pub async fn actions(&self) -> Result<ActionsBillingUsage> {
let route = format!("{}/actions", self.owner.legacy_prefix());
self.crab.get(route, None::<&()>).await
}
pub async fn packages(&self) -> Result<PackagesBillingUsage> {
let route = format!("{}/packages", self.owner.legacy_prefix());
self.crab.get(route, None::<&()>).await
}
pub async fn shared_storage(&self) -> Result<CombinedBillingUsage> {
let route = format!("{}/shared-storage", self.owner.legacy_prefix());
self.crab.get(route, None::<&()>).await
}
pub fn usage(&self, year: u32) -> GetBillingUsageBuilder<'octo, '_> {
GetBillingUsageBuilder::new(self, year)
}
pub fn usage_summary(&self, year: u32) -> GetBillingUsageSummaryBuilder<'octo, '_> {
GetBillingUsageSummaryBuilder::new(self, year)
}
pub fn ai_credit_usage(&self, year: u32) -> GetBillingAiCreditUsageBuilder<'octo, '_> {
GetBillingAiCreditUsageBuilder::new(self, year)
}
pub fn premium_request_usage(
&self,
year: u32,
) -> GetBillingPremiumRequestUsageBuilder<'octo, '_> {
GetBillingPremiumRequestUsageBuilder::new(self, year)
}
pub fn budgets(&self) -> OrgBudgetsHandler<'octo, '_> {
OrgBudgetsHandler::new(self)
}
}
#[derive(serde::Serialize)]
pub struct GetBillingUsageBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r ScopedBillingHandler<'octo>,
year: u32,
#[serde(skip_serializing_if = "Option::is_none")]
month: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
day: Option<u8>,
}
impl<'octo, 'r> GetBillingUsageBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r ScopedBillingHandler<'octo>, year: u32) -> Self {
Self {
handler,
year,
month: None,
day: None,
}
}
pub fn month(mut self, month: impl Into<u8>) -> Self {
self.month = Some(month.into());
self
}
pub fn day(mut self, day: impl Into<u8>) -> Self {
self.day = Some(day.into());
self
}
pub async fn send(self) -> Result<BillingUsageReport> {
let route = format!("{}/usage", self.handler.owner.usage_prefix());
self.handler.crab.get(route, Some(&self)).await
}
}
#[derive(serde::Serialize)]
pub struct GetBillingUsageSummaryBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r ScopedBillingHandler<'octo>,
year: u32,
#[serde(skip_serializing_if = "Option::is_none")]
month: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
day: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
repository: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
product: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
sku: Option<String>,
}
impl<'octo, 'r> GetBillingUsageSummaryBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r ScopedBillingHandler<'octo>, year: u32) -> Self {
Self {
handler,
year,
month: None,
day: None,
repository: None,
product: None,
sku: None,
}
}
pub fn month(mut self, month: impl Into<u8>) -> Self {
self.month = Some(month.into());
self
}
pub fn day(mut self, day: impl Into<u8>) -> Self {
self.day = Some(day.into());
self
}
pub fn repository(mut self, repository: impl Into<String>) -> Self {
self.repository = Some(repository.into());
self
}
pub fn product(mut self, product: impl Into<String>) -> Self {
self.product = Some(product.into());
self
}
pub fn sku(mut self, sku: impl Into<String>) -> Self {
self.sku = Some(sku.into());
self
}
pub async fn send(self) -> Result<BillingUsageSummaryReport> {
let route = format!("{}/usage/summary", self.handler.owner.usage_prefix());
self.handler.crab.get(route, Some(&self)).await
}
}
#[derive(serde::Serialize)]
pub struct GetBillingAiCreditUsageBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r ScopedBillingHandler<'octo>,
year: u32,
#[serde(skip_serializing_if = "Option::is_none")]
month: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
day: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
user: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
product: Option<String>,
}
impl<'octo, 'r> GetBillingAiCreditUsageBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r ScopedBillingHandler<'octo>, year: u32) -> Self {
Self {
handler,
year,
month: None,
day: None,
user: None,
model: None,
product: None,
}
}
pub fn month(mut self, month: impl Into<u8>) -> Self {
self.month = Some(month.into());
self
}
pub fn day(mut self, day: impl Into<u8>) -> Self {
self.day = Some(day.into());
self
}
pub fn user(mut self, user: impl Into<String>) -> Self {
self.user = Some(user.into());
self
}
pub fn model(mut self, model: impl Into<String>) -> Self {
self.model = Some(model.into());
self
}
pub fn product(mut self, product: impl Into<String>) -> Self {
self.product = Some(product.into());
self
}
pub async fn send(self) -> Result<BillingAiCreditUsageReport> {
let route = format!("{}/ai_credit/usage", self.handler.owner.usage_prefix());
self.handler.crab.get(route, Some(&self)).await
}
}
#[derive(serde::Serialize)]
pub struct GetBillingPremiumRequestUsageBuilder<'octo, 'r> {
#[serde(skip)]
handler: &'r ScopedBillingHandler<'octo>,
year: u32,
#[serde(skip_serializing_if = "Option::is_none")]
month: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
day: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
user: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
product: Option<String>,
}
impl<'octo, 'r> GetBillingPremiumRequestUsageBuilder<'octo, 'r> {
pub(crate) fn new(handler: &'r ScopedBillingHandler<'octo>, year: u32) -> Self {
Self {
handler,
year,
month: None,
day: None,
user: None,
model: None,
product: None,
}
}
pub fn month(mut self, month: impl Into<u8>) -> Self {
self.month = Some(month.into());
self
}
pub fn day(mut self, day: impl Into<u8>) -> Self {
self.day = Some(day.into());
self
}
pub fn user(mut self, user: impl Into<String>) -> Self {
self.user = Some(user.into());
self
}
pub fn model(mut self, model: impl Into<String>) -> Self {
self.model = Some(model.into());
self
}
pub fn product(mut self, product: impl Into<String>) -> Self {
self.product = Some(product.into());
self
}
pub async fn send(self) -> Result<BillingPremiumRequestUsageReport> {
let route = format!(
"{}/premium_request/usage",
self.handler.owner.usage_prefix()
);
self.handler.crab.get(route, Some(&self)).await
}
}
pub struct OrgBudgetsHandler<'octo, 'r> {
handler: &'r ScopedBillingHandler<'octo>,
}
impl<'octo, 'r> OrgBudgetsHandler<'octo, 'r> {
pub(crate) fn new(handler: &'r ScopedBillingHandler<'octo>) -> Self {
Self { handler }
}
pub fn list(&self) -> ListBudgetsBuilder<'octo, 'r, '_> {
ListBudgetsBuilder::new(self)
}
pub async fn create(&self, body: &CreateBudget) -> Result<CreateBudgetResponse> {
let route = format!("{}/budgets", self.handler.owner.usage_prefix());
self.handler.crab.post(route, Some(body)).await
}
pub async fn get(&self, budget_id: impl AsRef<str>) -> Result<Budget> {
let route = format!(
"{}/budgets/{}",
self.handler.owner.usage_prefix(),
budget_id.as_ref()
);
self.handler.crab.get(route, None::<&()>).await
}
pub async fn update(
&self,
budget_id: impl AsRef<str>,
body: &UpdateBudget,
) -> Result<UpdateBudgetResponse> {
let route = format!(
"{}/budgets/{}",
self.handler.owner.usage_prefix(),
budget_id.as_ref()
);
self.handler.crab.patch(route, Some(body)).await
}
pub async fn delete(&self, budget_id: impl AsRef<str>) -> Result<DeleteBudgetResponse> {
let route = format!(
"{}/budgets/{}",
self.handler.owner.usage_prefix(),
budget_id.as_ref()
);
self.handler.crab.delete(route, None::<&()>).await
}
}
#[derive(serde::Serialize)]
pub struct ListBudgetsBuilder<'octo, 'r, 'b> {
#[serde(skip)]
budgets_handler: &'b OrgBudgetsHandler<'octo, 'r>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
user: Option<String>,
}
impl<'octo, 'r, 'b> ListBudgetsBuilder<'octo, 'r, 'b> {
pub(crate) fn new(budgets_handler: &'b OrgBudgetsHandler<'octo, 'r>) -> Self {
Self {
budgets_handler,
page: None,
per_page: None,
scope: None,
user: None,
}
}
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}
pub fn scope(mut self, scope: impl Into<String>) -> Self {
self.scope = Some(scope.into());
self
}
pub fn user(mut self, user: impl Into<String>) -> Self {
self.user = Some(user.into());
self
}
pub async fn send(self) -> Result<GetAllBudgets> {
let route = format!(
"{}/budgets",
self.budgets_handler.handler.owner.usage_prefix()
);
self.budgets_handler
.handler
.crab
.get(route, Some(&self))
.await
}
}