replace with generated api
This commit is contained in:
		
							parent
							
								
									77b390575a
								
							
						
					
					
						commit
						81b17abc8a
					
				
					 10 changed files with 12272 additions and 2491 deletions
				
			
		
							
								
								
									
										502
									
								
								src/admin.rs
									
										
									
									
									
								
							
							
						
						
									
										502
									
								
								src/admin.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,502 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
use std::collections::BTreeMap;
 | 
			
		||||
use std::fmt::Write;
 | 
			
		||||
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    pub async fn admin_get_crons(&self, query: CronQuery) -> Result<Vec<Cron>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_run_cron(&self, name: &str) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.post_unit(&format!("admin/cron/{name}"), &()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_get_emails(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: EmailListQuery,
 | 
			
		||||
    ) -> Result<Vec<Email>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_search_emails(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: EmailSearchQuery,
 | 
			
		||||
    ) -> Result<Vec<Email>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_get_hooks(&self, query: HookQuery) -> Result<Vec<Hook>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_create_hook(&self, opt: CreateHookOption) -> Result<Hook, ForgejoError> {
 | 
			
		||||
        self.post("admin/hooks", &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_get_hook(&self, id: u64) -> Result<Option<Hook>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("admin/hooks/{id}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("admin/hooks/{id}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_edit_hook(
 | 
			
		||||
        &self,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        opt: EditHookOption,
 | 
			
		||||
    ) -> Result<Hook, ForgejoError> {
 | 
			
		||||
        self.patch(&format!("admin/hooks/{id}"), &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_get_orgs(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: AdminOrganizationQuery,
 | 
			
		||||
    ) -> Result<Vec<Organization>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_unadopted_repos(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: UnadoptedRepoQuery,
 | 
			
		||||
    ) -> Result<Vec<String>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_adopt(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.post(&format!("admin/unadopted/{owner}/{repo}"), &())
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_delete_unadopted(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("admin/unadopted/{owner}/{repo}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_users(&self, query: AdminUserQuery) -> Result<Vec<User>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path()).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_create_user(&self, opt: CreateUserOption) -> Result<User, ForgejoError> {
 | 
			
		||||
        self.post("admin/users", &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_delete_user(&self, user: &str, purge: bool) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("admin/users/{user}?purge={purge}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_edit_user(
 | 
			
		||||
        &self,
 | 
			
		||||
        user: &str,
 | 
			
		||||
        opt: CreateUserOption,
 | 
			
		||||
    ) -> Result<User, ForgejoError> {
 | 
			
		||||
        self.patch(&format!("admin/users/{user}"), &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_add_key(
 | 
			
		||||
        &self,
 | 
			
		||||
        user: &str,
 | 
			
		||||
        opt: CreateKeyOption,
 | 
			
		||||
    ) -> Result<PublicKey, ForgejoError> {
 | 
			
		||||
        self.post(&format!("admin/users/{user}/keys"), &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_delete_key(&self, user: &str, id: u64) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("admin/users/{user}/keys/{id}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_create_org(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        opt: CreateOrgOption,
 | 
			
		||||
    ) -> Result<Organization, ForgejoError> {
 | 
			
		||||
        self.post(&format!("admin/users/{owner}/orgs"), &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_rename_user(
 | 
			
		||||
        &self,
 | 
			
		||||
        user: &str,
 | 
			
		||||
        opt: RenameUserOption,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.post_unit(&format!("admin/users/{user}/rename"), &opt)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn admin_create_repo(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        opt: CreateRepoOption,
 | 
			
		||||
    ) -> Result<Repository, ForgejoError> {
 | 
			
		||||
        self.post(&format!("admin/users/{owner}/repos"), &opt).await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Cron {
 | 
			
		||||
    pub exec_times: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub next: time::OffsetDateTime,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub prev: time::OffsetDateTime,
 | 
			
		||||
    pub schedule: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct CronQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl CronQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/cron?");
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Email {
 | 
			
		||||
    pub email: String,
 | 
			
		||||
    pub primary: bool,
 | 
			
		||||
    pub user_id: u64,
 | 
			
		||||
    pub username: String,
 | 
			
		||||
    pub verified: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct EmailListQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EmailListQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/emails?");
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct EmailSearchQuery {
 | 
			
		||||
    pub query: String,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EmailSearchQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/emails/search?");
 | 
			
		||||
        if !self.query.is_empty() {
 | 
			
		||||
            s.push_str("q=");
 | 
			
		||||
            s.push_str(&self.query);
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Hook {
 | 
			
		||||
    pub active: bool,
 | 
			
		||||
    pub authorization_header: String,
 | 
			
		||||
    pub branch_filter: String,
 | 
			
		||||
    pub config: std::collections::BTreeMap<String, String>,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub events: Vec<String>,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    #[serde(rename = "type")]
 | 
			
		||||
    pub _type: HookType,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
#[non_exhaustive]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum HookType {
 | 
			
		||||
    Forgejo,
 | 
			
		||||
    Dingtalk,
 | 
			
		||||
    Discord,
 | 
			
		||||
    Gitea,
 | 
			
		||||
    Gogs,
 | 
			
		||||
    Msteams,
 | 
			
		||||
    Slack,
 | 
			
		||||
    Telegram,
 | 
			
		||||
    Feishu,
 | 
			
		||||
    Wechatwork,
 | 
			
		||||
    Packagist,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct HookQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl HookQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/hooks?");
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateHookOption {
 | 
			
		||||
    pub active: Option<bool>,
 | 
			
		||||
    pub authorization_header: Option<String>,
 | 
			
		||||
    pub branch_filter: Option<String>,
 | 
			
		||||
    pub config: CreateHookOptionConfig,
 | 
			
		||||
    pub events: Vec<String>,
 | 
			
		||||
    #[serde(rename = "type")]
 | 
			
		||||
    pub _type: HookType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateHookOptionConfig {
 | 
			
		||||
    pub content_type: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    #[serde(flatten)]
 | 
			
		||||
    pub other: BTreeMap<String, String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditHookOption {
 | 
			
		||||
    pub active: Option<bool>,
 | 
			
		||||
    pub authorization_header: Option<String>,
 | 
			
		||||
    pub branch_filter: Option<String>,
 | 
			
		||||
    pub config: Option<BTreeMap<String, String>>,
 | 
			
		||||
    pub events: Option<Vec<String>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct AdminOrganizationQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AdminOrganizationQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/orgs?");
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct UnadoptedRepoQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
    pub pattern: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UnadoptedRepoQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/unadopted?");
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if !self.pattern.is_empty() {
 | 
			
		||||
            s.push_str("pattern=");
 | 
			
		||||
            s.push_str(&self.pattern);
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct AdminUserQuery {
 | 
			
		||||
    pub source_id: Option<u64>,
 | 
			
		||||
    pub login_name: String,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AdminUserQuery {
 | 
			
		||||
    fn path(&self) -> String {
 | 
			
		||||
        let mut s = String::from("admin/users?");
 | 
			
		||||
        if let Some(source_id) = self.source_id {
 | 
			
		||||
            s.push_str("source_id=");
 | 
			
		||||
            s.write_fmt(format_args!("{source_id}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if !self.login_name.is_empty() {
 | 
			
		||||
            s.push_str("login_name=");
 | 
			
		||||
            s.push_str(&self.login_name);
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateUserOption {
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub created_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub email: String,
 | 
			
		||||
    pub full_name: Option<String>,
 | 
			
		||||
    pub login_name: Option<String>,
 | 
			
		||||
    pub must_change_password: bool,
 | 
			
		||||
    pub password: String,
 | 
			
		||||
    pub restricted: bool,
 | 
			
		||||
    pub send_notify: bool,
 | 
			
		||||
    pub source_id: Option<u64>,
 | 
			
		||||
    pub username: String,
 | 
			
		||||
    pub visibility: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditUserOption {
 | 
			
		||||
    pub active: Option<bool>,
 | 
			
		||||
    pub admin: Option<bool>,
 | 
			
		||||
    pub allow_create_organization: Option<bool>,
 | 
			
		||||
    pub allow_git_hook: Option<bool>,
 | 
			
		||||
    pub allow_import_local: Option<bool>,
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub email: Option<String>,
 | 
			
		||||
    pub full_name: Option<String>,
 | 
			
		||||
    pub location: Option<String>,
 | 
			
		||||
    pub login_name: Option<String>,
 | 
			
		||||
    pub max_repo_creation: Option<u64>,
 | 
			
		||||
    pub must_change_password: Option<bool>,
 | 
			
		||||
    pub password: Option<String>,
 | 
			
		||||
    pub prohibit_login: Option<bool>,
 | 
			
		||||
    pub restricted: Option<bool>,
 | 
			
		||||
    pub source_id: Option<u64>,
 | 
			
		||||
    pub visibility: Option<String>,
 | 
			
		||||
    pub website: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateKeyOption {
 | 
			
		||||
    pub key: String,
 | 
			
		||||
    pub read_only: Option<bool>,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct PublicKey {
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub fingerprint: String,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub key: String,
 | 
			
		||||
    pub key_type: String,
 | 
			
		||||
    pub read_only: Option<bool>,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
    pub url: Option<Url>,
 | 
			
		||||
    pub user: User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateOrgOption {
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub full_name: Option<String>,
 | 
			
		||||
    pub location: Option<String>,
 | 
			
		||||
    pub repo_admin_change_team_access: Option<bool>,
 | 
			
		||||
    pub username: String,
 | 
			
		||||
    pub visibility: OrgVisibility,
 | 
			
		||||
    pub website: Option<Url>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
pub enum OrgVisibility {
 | 
			
		||||
    Public,
 | 
			
		||||
    Limited,
 | 
			
		||||
    Private,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct RenameUserOption {
 | 
			
		||||
    pub new_username: String,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12253
									
								
								src/generated.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12253
									
								
								src/generated.rs
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										347
									
								
								src/issue.rs
									
										
									
									
									
								
							
							
						
						
									
										347
									
								
								src/issue.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,347 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    pub async fn get_repo_issues(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        query: IssueQuery,
 | 
			
		||||
    ) -> Result<Vec<Issue>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_issue(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        opts: CreateIssueOption,
 | 
			
		||||
    ) -> Result<Issue, ForgejoError> {
 | 
			
		||||
        self.post(&format!("repos/{owner}/{repo}/issues"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_issue(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<Option<Issue>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/issues/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_issue(&self, owner: &str, repo: &str, id: u64) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/issues/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn edit_issue(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        opts: EditIssueOption,
 | 
			
		||||
    ) -> Result<Issue, ForgejoError> {
 | 
			
		||||
        self.patch(&format!("repos/{owner}/{repo}/issues/{id}"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_repo_comments(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        query: RepoCommentQuery,
 | 
			
		||||
    ) -> Result<Vec<Comment>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_issue_comments(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        issue_id: u64,
 | 
			
		||||
        query: IssueCommentQuery,
 | 
			
		||||
    ) -> Result<Vec<Comment>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo, issue_id)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_comment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        issue_id: u64,
 | 
			
		||||
        opts: CreateIssueCommentOption,
 | 
			
		||||
    ) -> Result<Comment, ForgejoError> {
 | 
			
		||||
        self.post(
 | 
			
		||||
            &format!("repos/{owner}/{repo}/issues/{issue_id}/comments"),
 | 
			
		||||
            &opts,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_comment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<Option<Comment>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_comment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn edit_comment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        opts: EditIssueCommentOption,
 | 
			
		||||
    ) -> Result<Comment, ForgejoError> {
 | 
			
		||||
        self.patch(&format!("repos/{owner}/{repo}/issues/comments/{id}"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Issue {
 | 
			
		||||
    pub assets: Vec<Attachment>,
 | 
			
		||||
    pub assignee: Option<User>,
 | 
			
		||||
    pub assignees: Option<Vec<User>>,
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub closed_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub comments: u64,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_date: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub is_locked: bool,
 | 
			
		||||
    pub labels: Vec<Label>,
 | 
			
		||||
    pub milestone: Option<Milestone>,
 | 
			
		||||
    pub number: u64,
 | 
			
		||||
    pub original_author: String,
 | 
			
		||||
    pub original_author_id: u64,
 | 
			
		||||
    pub pin_order: u64,
 | 
			
		||||
    pub pull_request: Option<PullRequestMeta>,
 | 
			
		||||
    #[serde(rename = "ref")]
 | 
			
		||||
    pub _ref: String,
 | 
			
		||||
    pub repository: RepositoryMeta,
 | 
			
		||||
    pub state: State,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    pub user: User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Label {
 | 
			
		||||
    pub color: String,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub exclusive: bool,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Attachment {
 | 
			
		||||
    pub browser_download_url: Url,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub download_count: u64,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub size: u64,
 | 
			
		||||
    pub uuid: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditAttachmentOption {
 | 
			
		||||
    pub name: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Copy)]
 | 
			
		||||
pub enum State {
 | 
			
		||||
    #[serde(rename = "open")]
 | 
			
		||||
    Open,
 | 
			
		||||
    #[serde(rename = "closed")]
 | 
			
		||||
    Closed,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl State {
 | 
			
		||||
    pub(crate) fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            State::Open => "open",
 | 
			
		||||
            State::Closed => "closed",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Comment {
 | 
			
		||||
    pub assets: Vec<Attachment>,
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub issue_url: Url,
 | 
			
		||||
    pub original_author: String,
 | 
			
		||||
    pub original_author_id: u64,
 | 
			
		||||
    #[serde(deserialize_with = "crate::none_if_blank_url")]
 | 
			
		||||
    pub pull_request_url: Option<Url>,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
    pub user: User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct IssueQuery {
 | 
			
		||||
    pub state: Option<State>,
 | 
			
		||||
    pub labels: Vec<String>,
 | 
			
		||||
    pub query: Option<String>,
 | 
			
		||||
    pub _type: Option<IssueQueryType>,
 | 
			
		||||
    pub milestones: Vec<String>,
 | 
			
		||||
    pub since: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub before: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub created_by: Option<String>,
 | 
			
		||||
    pub assigned_by: Option<String>,
 | 
			
		||||
    pub mentioned_by: Option<String>,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IssueQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str) -> String {
 | 
			
		||||
        format!("repos/{owner}/{repo}/issues?state={}&labels={}&q={}&type={}&milestones={}&since={}&before={}&created_by={}&assigned_by={}&mentioned_by={}&page={}&limit={}",
 | 
			
		||||
            self.state.map(|s| s.as_str()).unwrap_or_default(),
 | 
			
		||||
            self.labels.join(","),
 | 
			
		||||
            self.query.as_deref().unwrap_or_default(),
 | 
			
		||||
            self._type.map(|t| t.as_str()).unwrap_or_default(),
 | 
			
		||||
            self.milestones.join(","),
 | 
			
		||||
            self.since.map(|t| t.format(&time::format_description::well_known::Rfc3339).unwrap()).unwrap_or_default(),
 | 
			
		||||
            self.before.map(|t| t.format(&time::format_description::well_known::Rfc3339).unwrap()).unwrap_or_default(),
 | 
			
		||||
            self.created_by.as_deref().unwrap_or_default(),
 | 
			
		||||
            self.assigned_by.as_deref().unwrap_or_default(),
 | 
			
		||||
            self.mentioned_by.as_deref().unwrap_or_default(),
 | 
			
		||||
            self.page.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
            self.limit.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Clone, Copy)]
 | 
			
		||||
pub enum IssueQueryType {
 | 
			
		||||
    Issues,
 | 
			
		||||
    Pulls,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IssueQueryType {
 | 
			
		||||
    fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            IssueQueryType::Issues => "issues",
 | 
			
		||||
            IssueQueryType::Pulls => "pulls",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct IssueCommentQuery {
 | 
			
		||||
    pub since: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub before: Option<time::OffsetDateTime>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IssueCommentQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str, issue_id: u64) -> String {
 | 
			
		||||
        format!(
 | 
			
		||||
            "repos/{owner}/{repo}/issues/{issue_id}/comments?since={}&before={}",
 | 
			
		||||
            self.since
 | 
			
		||||
                .map(|t| t
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap())
 | 
			
		||||
                .unwrap_or_default(),
 | 
			
		||||
            self.before
 | 
			
		||||
                .map(|t| t
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap())
 | 
			
		||||
                .unwrap_or_default(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct RepoCommentQuery {
 | 
			
		||||
    pub since: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub before: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RepoCommentQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str) -> String {
 | 
			
		||||
        format!(
 | 
			
		||||
            "repos/{owner}/{repo}/issues/comments?since={}&before={}&page={}&limit={}",
 | 
			
		||||
            self.since
 | 
			
		||||
                .map(|t| t
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap())
 | 
			
		||||
                .unwrap_or_default(),
 | 
			
		||||
            self.before
 | 
			
		||||
                .map(|t| t
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap())
 | 
			
		||||
                .unwrap_or_default(),
 | 
			
		||||
            self.page.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
            self.limit.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct CreateIssueOption {
 | 
			
		||||
    pub assignees: Vec<String>,
 | 
			
		||||
    pub body: Option<String>,
 | 
			
		||||
    pub closed: Option<bool>,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_date: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub labels: Vec<u64>,
 | 
			
		||||
    pub milestone: Option<u64>,
 | 
			
		||||
    pub _ref: Option<String>,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditIssueOption {
 | 
			
		||||
    pub assignees: Vec<String>,
 | 
			
		||||
    pub body: Option<String>,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_date: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub labels: Vec<u64>,
 | 
			
		||||
    pub milestone: Option<u64>,
 | 
			
		||||
    pub _ref: Option<String>,
 | 
			
		||||
    pub state: Option<State>,
 | 
			
		||||
    pub title: Option<String>,
 | 
			
		||||
    pub unset_due_date: Option<bool>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct CreateIssueCommentOption {
 | 
			
		||||
    pub body: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditIssueCommentOption {
 | 
			
		||||
    pub body: String,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										220
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										220
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
use reqwest::{Client, Request, StatusCode};
 | 
			
		||||
use serde::{de::DeserializeOwned, Serialize};
 | 
			
		||||
use soft_assert::*;
 | 
			
		||||
use url::Url;
 | 
			
		||||
use zeroize::Zeroize;
 | 
			
		||||
| 
						 | 
				
			
			@ -9,23 +8,9 @@ pub struct Forgejo {
 | 
			
		|||
    client: Client,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mod admin;
 | 
			
		||||
mod issue;
 | 
			
		||||
mod misc;
 | 
			
		||||
mod notification;
 | 
			
		||||
mod organization;
 | 
			
		||||
mod package;
 | 
			
		||||
mod repository;
 | 
			
		||||
mod user;
 | 
			
		||||
mod generated;
 | 
			
		||||
 | 
			
		||||
pub use admin::*;
 | 
			
		||||
pub use issue::*;
 | 
			
		||||
pub use misc::*;
 | 
			
		||||
pub use notification::*;
 | 
			
		||||
pub use organization::*;
 | 
			
		||||
pub use package::*;
 | 
			
		||||
pub use repository::*;
 | 
			
		||||
pub use user::*;
 | 
			
		||||
pub use generated::structs;
 | 
			
		||||
 | 
			
		||||
#[derive(thiserror::Error, Debug)]
 | 
			
		||||
pub enum ForgejoError {
 | 
			
		||||
| 
						 | 
				
			
			@ -134,202 +119,35 @@ impl Forgejo {
 | 
			
		|||
        Ok(Self { url, client })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn get<T: DeserializeOwned>(&self, path: &str) -> Result<T, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.get(url).build()?;
 | 
			
		||||
        self.execute(request).await
 | 
			
		||||
    fn get(&self, path: &str) -> reqwest::RequestBuilder {
 | 
			
		||||
        let url = self.url.join("api/v1").unwrap().join(path).unwrap();
 | 
			
		||||
        self.client.get(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn get_opt<T: DeserializeOwned>(&self, path: &str) -> Result<Option<T>, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.get(url).build()?;
 | 
			
		||||
        self.execute_opt(request).await
 | 
			
		||||
    fn put(&self, path: &str) -> reqwest::RequestBuilder {
 | 
			
		||||
        let url = self.url.join("api/v1").unwrap().join(path).unwrap();
 | 
			
		||||
        self.client.put(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn get_str(&self, path: &str) -> Result<String, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.get(url).build()?;
 | 
			
		||||
        self.execute_str(request).await
 | 
			
		||||
    fn post(&self, path: &str) -> reqwest::RequestBuilder {
 | 
			
		||||
        let url = self.url.join("api/v1").unwrap().join(path).unwrap();
 | 
			
		||||
        self.client.post(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn get_exists(&self, path: &str) -> Result<bool, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.get(url).build()?;
 | 
			
		||||
        self.execute_exists(request).await
 | 
			
		||||
    fn delete(&self, path: &str) -> reqwest::RequestBuilder {
 | 
			
		||||
        let url = self.url.join("api/v1").unwrap().join(path).unwrap();
 | 
			
		||||
        self.client.post(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn post<T: Serialize, U: DeserializeOwned>(
 | 
			
		||||
        &self,
 | 
			
		||||
        path: &str,
 | 
			
		||||
        body: &T,
 | 
			
		||||
    ) -> Result<U, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.post(url).json(body).build()?;
 | 
			
		||||
        self.execute(request).await
 | 
			
		||||
    fn patch(&self, path: &str) -> reqwest::RequestBuilder {
 | 
			
		||||
        let url = self.url.join("api/v1").unwrap().join(path).unwrap();
 | 
			
		||||
        self.client.post(url)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn post_multipart<T: DeserializeOwned>(
 | 
			
		||||
        &self,
 | 
			
		||||
        path: &str,
 | 
			
		||||
        body: reqwest::multipart::Form,
 | 
			
		||||
    ) -> Result<T, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.post(url).multipart(body).build()?;
 | 
			
		||||
        self.execute(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn post_str_out<T: Serialize>(
 | 
			
		||||
        &self,
 | 
			
		||||
        path: &str,
 | 
			
		||||
        body: &T,
 | 
			
		||||
    ) -> Result<String, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.post(url).json(body).build()?;
 | 
			
		||||
        self.execute_str(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn post_unit<T: Serialize>(&self, path: &str, body: &T) -> Result<(), ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.post(url).json(body).build()?;
 | 
			
		||||
        self.execute_unit(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn post_raw(&self, path: &str, body: String) -> Result<String, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.post(url).body(body).build()?;
 | 
			
		||||
        self.execute_str(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn delete(&self, path: &str) -> Result<(), ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.delete(url).build()?;
 | 
			
		||||
        self.execute_unit(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn patch<T: Serialize, U: DeserializeOwned>(
 | 
			
		||||
        &self,
 | 
			
		||||
        path: &str,
 | 
			
		||||
        body: &T,
 | 
			
		||||
    ) -> Result<U, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.patch(url).json(body).build()?;
 | 
			
		||||
        self.execute(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn put<T: DeserializeOwned>(&self, path: &str) -> Result<T, ForgejoError> {
 | 
			
		||||
        let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
 | 
			
		||||
        let request = self.client.put(url).build()?;
 | 
			
		||||
        self.execute(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn execute<T: DeserializeOwned>(&self, request: Request) -> Result<T, ForgejoError> {
 | 
			
		||||
    async fn execute(&self, request: Request) -> Result<reqwest::Response, ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => {
 | 
			
		||||
                let body = response.text().await?;
 | 
			
		||||
                let out =
 | 
			
		||||
                    serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?;
 | 
			
		||||
                Ok(out)
 | 
			
		||||
            }
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
                    .json::<ErrorMessage>()
 | 
			
		||||
                    .await?
 | 
			
		||||
                    .message
 | 
			
		||||
                    .unwrap_or_else(|| String::from("[no message]")),
 | 
			
		||||
            )),
 | 
			
		||||
            status => Err(ForgejoError::UnexpectedStatusCode(status)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Like `execute`, but returns a `String`.
 | 
			
		||||
    async fn execute_opt_raw(
 | 
			
		||||
        &self,
 | 
			
		||||
        request: Request,
 | 
			
		||||
    ) -> Result<Option<bytes::Bytes>, ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => Ok(Some(response.bytes().await?)),
 | 
			
		||||
            StatusCode::NOT_FOUND => Ok(None),
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
                    .json::<ErrorMessage>()
 | 
			
		||||
                    .await?
 | 
			
		||||
                    .message
 | 
			
		||||
                    .unwrap_or_else(|| String::from("[no message]")),
 | 
			
		||||
            )),
 | 
			
		||||
            status => Err(ForgejoError::UnexpectedStatusCode(status)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Like `execute`, but returns a `String`.
 | 
			
		||||
    async fn execute_str(&self, request: Request) -> Result<String, ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => Ok(response.text().await?),
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
                    .json::<ErrorMessage>()
 | 
			
		||||
                    .await?
 | 
			
		||||
                    .message
 | 
			
		||||
                    .unwrap_or_else(|| String::from("[no message]")),
 | 
			
		||||
            )),
 | 
			
		||||
            status => Err(ForgejoError::UnexpectedStatusCode(status)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Like `execute`, but returns unit.
 | 
			
		||||
    async fn execute_unit(&self, request: Request) -> Result<(), ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => Ok(()),
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
                    .json::<ErrorMessage>()
 | 
			
		||||
                    .await?
 | 
			
		||||
                    .message
 | 
			
		||||
                    .unwrap_or_else(|| String::from("[no message]")),
 | 
			
		||||
            )),
 | 
			
		||||
            status => Err(ForgejoError::UnexpectedStatusCode(status)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Like `execute`, but returns `Ok(None)` on 404.
 | 
			
		||||
    async fn execute_opt<T: DeserializeOwned>(
 | 
			
		||||
        &self,
 | 
			
		||||
        request: Request,
 | 
			
		||||
    ) -> Result<Option<T>, ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => {
 | 
			
		||||
                let body = response.text().await?;
 | 
			
		||||
                let out =
 | 
			
		||||
                    serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?;
 | 
			
		||||
                Ok(out)
 | 
			
		||||
            }
 | 
			
		||||
            StatusCode::NOT_FOUND => Ok(None),
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
                    .json::<ErrorMessage>()
 | 
			
		||||
                    .await?
 | 
			
		||||
                    .message
 | 
			
		||||
                    .unwrap_or_else(|| String::from("[no message]")),
 | 
			
		||||
            )),
 | 
			
		||||
            status => Err(ForgejoError::UnexpectedStatusCode(status)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Like `execute`, but returns `false` on 404.
 | 
			
		||||
    async fn execute_exists(&self, request: Request) -> Result<bool, ForgejoError> {
 | 
			
		||||
        let response = self.client.execute(request).await?;
 | 
			
		||||
        match response.status() {
 | 
			
		||||
            status if status.is_success() => Ok(true),
 | 
			
		||||
            StatusCode::NOT_FOUND => Ok(false),
 | 
			
		||||
            status if status.is_success() => Ok(response),
 | 
			
		||||
            status if status.is_client_error() => Err(ForgejoError::ApiError(
 | 
			
		||||
                status,
 | 
			
		||||
                response
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										162
									
								
								src/misc.rs
									
										
									
									
									
								
							
							
						
						
									
										162
									
								
								src/misc.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,162 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    pub async fn get_gitignore_templates(&self) -> Result<Vec<String>, ForgejoError> {
 | 
			
		||||
        self.get("gitignore/templates").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_gitignore_template(
 | 
			
		||||
        &self,
 | 
			
		||||
        name: &str,
 | 
			
		||||
    ) -> Result<Option<GitignoreTemplateInfo>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("gitignore/templates/{name}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_label_templates(&self) -> Result<Vec<String>, ForgejoError> {
 | 
			
		||||
        self.get("label/templates").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_label_template(&self, name: &str) -> Result<Vec<LabelTemplate>, ForgejoError> {
 | 
			
		||||
        self.get(&format!("label/templates/{name}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_licenses(&self) -> Result<Vec<LicenseTemplateListEntry>, ForgejoError> {
 | 
			
		||||
        self.get("licenses").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_license(
 | 
			
		||||
        &self,
 | 
			
		||||
        name: &str,
 | 
			
		||||
    ) -> Result<Option<GitignoreTemplateInfo>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("license/{name}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn render_markdown(&self, opt: MarkdownOption) -> Result<String, ForgejoError> {
 | 
			
		||||
        self.post_str_out("markdown", &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn render_markdown_raw(&self, body: String) -> Result<String, ForgejoError> {
 | 
			
		||||
        self.post_raw("markdown/raw", body).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn render_markup(&self, opt: MarkupOption) -> Result<String, ForgejoError> {
 | 
			
		||||
        self.post_str_out("markup", &opt).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn nodeinfo(&self) -> Result<NodeInfo, ForgejoError> {
 | 
			
		||||
        self.get("nodeinfo").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn signing_key(&self) -> Result<String, ForgejoError> {
 | 
			
		||||
        self.get_str("signing-key.gpg").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn version(&self) -> Result<ServerVersion, ForgejoError> {
 | 
			
		||||
        self.get("version").await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct GitignoreTemplateInfo {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub source: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct LabelTemplate {
 | 
			
		||||
    pub color: String,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub exclusive: bool,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct LicenseTemplateListEntry {
 | 
			
		||||
    pub key: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct LicenseTemplateInfo {
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    pub implementation: String,
 | 
			
		||||
    pub key: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct MarkdownOption {
 | 
			
		||||
    #[serde(rename = "Context")]
 | 
			
		||||
    pub context: String,
 | 
			
		||||
    #[serde(rename = "Mode")]
 | 
			
		||||
    pub mode: String,
 | 
			
		||||
    #[serde(rename = "Text")]
 | 
			
		||||
    pub text: String,
 | 
			
		||||
    #[serde(rename = "Wiki")]
 | 
			
		||||
    pub wiki: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct MarkupOption {
 | 
			
		||||
    #[serde(rename = "Context")]
 | 
			
		||||
    pub context: String,
 | 
			
		||||
    #[serde(rename = "FilePath")]
 | 
			
		||||
    pub file_path: String,
 | 
			
		||||
    #[serde(rename = "Mode")]
 | 
			
		||||
    pub mode: String,
 | 
			
		||||
    #[serde(rename = "Text")]
 | 
			
		||||
    pub text: String,
 | 
			
		||||
    #[serde(rename = "Wiki")]
 | 
			
		||||
    pub wiki: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NodeInfo {
 | 
			
		||||
    pub metadata: std::collections::BTreeMap<String, String>,
 | 
			
		||||
    #[serde(rename = "openRegistrations")]
 | 
			
		||||
    pub open_registrations: bool,
 | 
			
		||||
    pub protocols: Vec<String>,
 | 
			
		||||
    pub services: NodeInfoServices,
 | 
			
		||||
    pub software: NodeInfoSoftware,
 | 
			
		||||
    pub usage: NodeInfoUsage,
 | 
			
		||||
    pub version: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NodeInfoServices {
 | 
			
		||||
    pub inbound: Vec<String>,
 | 
			
		||||
    pub outbound: Vec<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NodeInfoSoftware {
 | 
			
		||||
    pub homepage: Url,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub repository: Url,
 | 
			
		||||
    pub version: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NodeInfoUsage {
 | 
			
		||||
    #[serde(rename = "localComments")]
 | 
			
		||||
    pub local_comments: u64,
 | 
			
		||||
    #[serde(rename = "localPosts")]
 | 
			
		||||
    pub local_posts: u64,
 | 
			
		||||
    pub users: NodeInfoUsageUsers,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NodeInfoUsageUsers {
 | 
			
		||||
    #[serde(rename = "activeHalfYear")]
 | 
			
		||||
    pub active_half_year: u64,
 | 
			
		||||
    #[serde(rename = "activeMonth")]
 | 
			
		||||
    pub active_month: u64,
 | 
			
		||||
    pub total: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct ServerVersion {
 | 
			
		||||
    pub version: String,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,273 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    pub async fn notifications(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: NotificationQuery,
 | 
			
		||||
    ) -> Result<Vec<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.get(&format!("notifications?{}", query.query_string()))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn set_notifications_state(
 | 
			
		||||
        &self,
 | 
			
		||||
        query: NotificationPutQuery,
 | 
			
		||||
    ) -> Result<Vec<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.put(&format!("notifications?{}", query.query_string()))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn notification_count(&self) -> Result<Vec<NotificationCount>, ForgejoError> {
 | 
			
		||||
        self.get("notifications/new").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_notification(
 | 
			
		||||
        &self,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<Option<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("notifications/threads/{id}")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn set_notification_state(
 | 
			
		||||
        &self,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        to_status: ToStatus,
 | 
			
		||||
    ) -> Result<Option<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.patch(
 | 
			
		||||
            &format!(
 | 
			
		||||
                "notifications/threads/{id}?to-status={}",
 | 
			
		||||
                to_status.as_str()
 | 
			
		||||
            ),
 | 
			
		||||
            &(),
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_repo_notifications(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        query: NotificationQuery,
 | 
			
		||||
    ) -> Result<Vec<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.get(&format!(
 | 
			
		||||
            "repos/{owner}/{name}/notifications?{}",
 | 
			
		||||
            query.query_string()
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn set_repo_notifications_state(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        query: NotificationPutQuery,
 | 
			
		||||
    ) -> Result<Vec<NotificationThread>, ForgejoError> {
 | 
			
		||||
        self.put(&format!(
 | 
			
		||||
            "repos/{owner}/{name}/notifications?{}",
 | 
			
		||||
            query.query_string()
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct NotificationQuery {
 | 
			
		||||
    pub all: bool,
 | 
			
		||||
    pub include_unread: bool,
 | 
			
		||||
    pub include_read: bool,
 | 
			
		||||
    pub include_pinned: bool,
 | 
			
		||||
    pub subject_type: Option<NotificationSubjectType>,
 | 
			
		||||
    pub since: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub before: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for NotificationQuery {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        NotificationQuery {
 | 
			
		||||
            all: false,
 | 
			
		||||
            include_unread: true,
 | 
			
		||||
            include_read: false,
 | 
			
		||||
            include_pinned: true,
 | 
			
		||||
            subject_type: None,
 | 
			
		||||
            since: None,
 | 
			
		||||
            before: None,
 | 
			
		||||
            page: None,
 | 
			
		||||
            limit: None,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NotificationQuery {
 | 
			
		||||
    fn query_string(&self) -> String {
 | 
			
		||||
        use std::fmt::Write;
 | 
			
		||||
        let mut s = String::new();
 | 
			
		||||
        if self.all {
 | 
			
		||||
            s.push_str("all=true&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_unread {
 | 
			
		||||
            s.push_str("status-types=unread&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_read {
 | 
			
		||||
            s.push_str("status-types=read&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_pinned {
 | 
			
		||||
            s.push_str("status-types=pinned&");
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(subject_type) = self.subject_type {
 | 
			
		||||
            s.push_str("subject-type=");
 | 
			
		||||
            s.push_str(subject_type.as_str());
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(since) = &self.since {
 | 
			
		||||
            s.push_str("since=");
 | 
			
		||||
            s.push_str(
 | 
			
		||||
                &since
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            );
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(before) = &self.before {
 | 
			
		||||
            s.push_str("before=");
 | 
			
		||||
            s.push_str(
 | 
			
		||||
                &before
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            );
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Copy)]
 | 
			
		||||
pub enum NotificationSubjectType {
 | 
			
		||||
    Issue,
 | 
			
		||||
    Pull,
 | 
			
		||||
    Commit,
 | 
			
		||||
    Repository,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NotificationSubjectType {
 | 
			
		||||
    fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            NotificationSubjectType::Issue => "issue",
 | 
			
		||||
            NotificationSubjectType::Pull => "pull",
 | 
			
		||||
            NotificationSubjectType::Commit => "commit",
 | 
			
		||||
            NotificationSubjectType::Repository => "repository",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NotificationThread {
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub pinned: bool,
 | 
			
		||||
    pub repository: Repository,
 | 
			
		||||
    pub subject: NotificationSubject,
 | 
			
		||||
    pub unread: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NotificationSubject {
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub latest_comment_html_url: Url,
 | 
			
		||||
    pub latest_comment_url: Url,
 | 
			
		||||
    pub state: String,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
    #[serde(rename = "type")]
 | 
			
		||||
    pub _type: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct NotificationPutQuery {
 | 
			
		||||
    pub last_read_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub all: bool,
 | 
			
		||||
    pub include_unread: bool,
 | 
			
		||||
    pub include_read: bool,
 | 
			
		||||
    pub include_pinned: bool,
 | 
			
		||||
    pub to_status: ToStatus,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for NotificationPutQuery {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        NotificationPutQuery {
 | 
			
		||||
            last_read_at: None,
 | 
			
		||||
            all: false,
 | 
			
		||||
            include_unread: true,
 | 
			
		||||
            include_read: false,
 | 
			
		||||
            include_pinned: false,
 | 
			
		||||
            to_status: ToStatus::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NotificationPutQuery {
 | 
			
		||||
    fn query_string(&self) -> String {
 | 
			
		||||
        let mut s = String::new();
 | 
			
		||||
        if let Some(last_read_at) = &self.last_read_at {
 | 
			
		||||
            s.push_str("since=");
 | 
			
		||||
            s.push_str(
 | 
			
		||||
                &last_read_at
 | 
			
		||||
                    .format(&time::format_description::well_known::Rfc3339)
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            );
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if self.all {
 | 
			
		||||
            s.push_str("all=true&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_unread {
 | 
			
		||||
            s.push_str("status-types=unread&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_read {
 | 
			
		||||
            s.push_str("status-types=read&");
 | 
			
		||||
        }
 | 
			
		||||
        if self.include_pinned {
 | 
			
		||||
            s.push_str("status-types=pinned&");
 | 
			
		||||
        }
 | 
			
		||||
        s.push_str("subject-type=");
 | 
			
		||||
        s.push_str(self.to_status.as_str());
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub enum ToStatus {
 | 
			
		||||
    #[default]
 | 
			
		||||
    Read,
 | 
			
		||||
    Unread,
 | 
			
		||||
    Pinned,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToStatus {
 | 
			
		||||
    fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            ToStatus::Read => "read",
 | 
			
		||||
            ToStatus::Unread => "unread",
 | 
			
		||||
            ToStatus::Pinned => "pinned",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct NotificationCount {
 | 
			
		||||
    pub new: u64,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,30 +0,0 @@
 | 
			
		|||
use crate::*;
 | 
			
		||||
use std::collections::BTreeMap;
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Organization {
 | 
			
		||||
    #[serde(deserialize_with = "crate::none_if_blank_url")]
 | 
			
		||||
    pub avatar_url: Option<Url>,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub full_name: String,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub location: Option<String>,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub repo_admin_change_team_access: bool,
 | 
			
		||||
    pub visibility: String,
 | 
			
		||||
    #[serde(deserialize_with = "crate::none_if_blank_url")]
 | 
			
		||||
    pub website: Option<Url>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Team {
 | 
			
		||||
    pub can_create_org_repo: bool,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub includes_all_repositories: bool,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub organization: Organization,
 | 
			
		||||
    pub permission: String,
 | 
			
		||||
    pub units: Vec<String>,
 | 
			
		||||
    pub units_map: BTreeMap<String, String>,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										174
									
								
								src/package.rs
									
										
									
									
									
								
							
							
						
						
									
										174
									
								
								src/package.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,174 +0,0 @@
 | 
			
		|||
use std::fmt::Write;
 | 
			
		||||
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    pub async fn get_user_packages(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        query: PackagesQuery,
 | 
			
		||||
    ) -> Result<Vec<Package>, ForgejoError> {
 | 
			
		||||
        self.get(&query.path(owner)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_package(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        _type: PackageType,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        version: &str,
 | 
			
		||||
    ) -> Result<Option<Package>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!(
 | 
			
		||||
            "packages/{owner}/{}/{name}/{version}",
 | 
			
		||||
            _type.as_str()
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_package(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        _type: PackageType,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        version: &str,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!(
 | 
			
		||||
            "packages/{owner}/{}/{name}/{version}",
 | 
			
		||||
            _type.as_str()
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_package_files(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        _type: PackageType,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        version: &str,
 | 
			
		||||
    ) -> Result<Vec<PackageFile>, ForgejoError> {
 | 
			
		||||
        self.get(&format!(
 | 
			
		||||
            "packages/{owner}/{}/{name}/{version}",
 | 
			
		||||
            _type.as_str()
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct PackagesQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
    pub kind: Option<PackageType>,
 | 
			
		||||
    pub query: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PackagesQuery {
 | 
			
		||||
    fn path(&self, owner: &str) -> String {
 | 
			
		||||
        let mut s = String::from("packages/");
 | 
			
		||||
        s.push_str(owner);
 | 
			
		||||
        s.push('?');
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to string can't fail");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(kind) = self.kind {
 | 
			
		||||
            s.push_str("type=");
 | 
			
		||||
            s.push_str(kind.as_str());
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if !self.query.is_empty() {
 | 
			
		||||
            s.push_str("q=");
 | 
			
		||||
            s.push_str(&self.query);
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
 | 
			
		||||
#[serde(rename_all = "lowercase")]
 | 
			
		||||
#[non_exhaustive]
 | 
			
		||||
pub enum PackageType {
 | 
			
		||||
    Alpine,
 | 
			
		||||
    Cargo,
 | 
			
		||||
    Chef,
 | 
			
		||||
    Composer,
 | 
			
		||||
    Conan,
 | 
			
		||||
    Conda,
 | 
			
		||||
    Container,
 | 
			
		||||
    Cran,
 | 
			
		||||
    Debian,
 | 
			
		||||
    Generic,
 | 
			
		||||
    Go,
 | 
			
		||||
    Helm,
 | 
			
		||||
    Maven,
 | 
			
		||||
    Npm,
 | 
			
		||||
    Nuget,
 | 
			
		||||
    Pub,
 | 
			
		||||
    Pypi,
 | 
			
		||||
    Rpm,
 | 
			
		||||
    RubyGems,
 | 
			
		||||
    Swift,
 | 
			
		||||
    Vagrant,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PackageType {
 | 
			
		||||
    fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            PackageType::Alpine => "alpine",
 | 
			
		||||
            PackageType::Cargo => "cargo",
 | 
			
		||||
            PackageType::Chef => "chef",
 | 
			
		||||
            PackageType::Composer => "composer",
 | 
			
		||||
            PackageType::Conan => "conan",
 | 
			
		||||
            PackageType::Conda => "conda",
 | 
			
		||||
            PackageType::Container => "container",
 | 
			
		||||
            PackageType::Cran => "cran",
 | 
			
		||||
            PackageType::Debian => "debian",
 | 
			
		||||
            PackageType::Generic => "generic",
 | 
			
		||||
            PackageType::Go => "go",
 | 
			
		||||
            PackageType::Helm => "helm",
 | 
			
		||||
            PackageType::Maven => "maven",
 | 
			
		||||
            PackageType::Npm => "npm",
 | 
			
		||||
            PackageType::Nuget => "nuget",
 | 
			
		||||
            PackageType::Pub => "pub",
 | 
			
		||||
            PackageType::Pypi => "pypi",
 | 
			
		||||
            PackageType::Rpm => "rpm",
 | 
			
		||||
            PackageType::RubyGems => "rubygems",
 | 
			
		||||
            PackageType::Swift => "swift",
 | 
			
		||||
            PackageType::Vagrant => "vagrant",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Package {
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub creator: User,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub owner: User,
 | 
			
		||||
    pub repository: Option<Repository>,
 | 
			
		||||
    pub _type: PackageType,
 | 
			
		||||
    pub version: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct PackageFile {
 | 
			
		||||
    #[serde(rename = "Size")]
 | 
			
		||||
    pub size: u64,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub md5: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub sha1: String,
 | 
			
		||||
    pub sha256: String,
 | 
			
		||||
    pub sha512: String,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,743 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
/// Repository operations.
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    /// Gets info about the specified repository.
 | 
			
		||||
    pub async fn get_repo(
 | 
			
		||||
        &self,
 | 
			
		||||
        user: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
    ) -> Result<Option<Repository>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{user}/{repo}/")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a repository.
 | 
			
		||||
    pub async fn create_repo(&self, repo: CreateRepoOption) -> Result<Repository, ForgejoError> {
 | 
			
		||||
        self.post("user/repos", &repo).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_pulls(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        query: PullQuery,
 | 
			
		||||
    ) -> Result<Vec<PullRequest>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_pr(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        opts: CreatePullRequestOption,
 | 
			
		||||
    ) -> Result<PullRequest, ForgejoError> {
 | 
			
		||||
        self.post(&format!("repos/{owner}/{repo}/pulls"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn is_merged(&self, owner: &str, repo: &str, pr: u64) -> Result<bool, ForgejoError> {
 | 
			
		||||
        self.get_exists(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn merge_pr(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        pr: u64,
 | 
			
		||||
        opts: MergePullRequestOption,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.post_unit(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn cancel_merge(&self, owner: &str, repo: &str, pr: u64) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_releases(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        query: ReleaseQuery,
 | 
			
		||||
    ) -> Result<Vec<Release>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_release(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<Option<Release>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/releases/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_release_by_tag(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        tag: &str,
 | 
			
		||||
    ) -> Result<Option<Release>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_release(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/releases/{id}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_release_by_tag(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        tag: &str,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn edit_release(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        opts: EditReleaseOption,
 | 
			
		||||
    ) -> Result<Release, ForgejoError> {
 | 
			
		||||
        self.patch(&format!("repos/{owner}/{repo}/releases/{id}"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_release_attachments(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
    ) -> Result<Vec<Attachment>, ForgejoError> {
 | 
			
		||||
        self.get(&format!("repos/{owner}/{repo}/releases/{id}/assets"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_release_attachment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        release_id: u64,
 | 
			
		||||
        attachment_id: u64,
 | 
			
		||||
    ) -> Result<Attachment, ForgejoError> {
 | 
			
		||||
        self.get(&format!(
 | 
			
		||||
            "repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_release_attachment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        id: u64,
 | 
			
		||||
        name: &str,
 | 
			
		||||
        file: Vec<u8>,
 | 
			
		||||
    ) -> Result<Attachment, ForgejoError> {
 | 
			
		||||
        self.post_multipart(
 | 
			
		||||
            &format!("repos/{owner}/{repo}/releases/{id}/assets?name={name}"),
 | 
			
		||||
            reqwest::multipart::Form::new().part(
 | 
			
		||||
                "attachment",
 | 
			
		||||
                reqwest::multipart::Part::bytes(file)
 | 
			
		||||
                    .file_name("file")
 | 
			
		||||
                    .mime_str("*/*")
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_release_attachment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        release_id: u64,
 | 
			
		||||
        attachment_id: u64,
 | 
			
		||||
    ) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!(
 | 
			
		||||
            "repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"
 | 
			
		||||
        ))
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn edit_release_attachment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        release_id: u64,
 | 
			
		||||
        attachment_id: u64,
 | 
			
		||||
        opts: EditAttachmentOption,
 | 
			
		||||
    ) -> Result<Attachment, ForgejoError> {
 | 
			
		||||
        self.patch(
 | 
			
		||||
            &format!("repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"),
 | 
			
		||||
            &opts,
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_release(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        opts: CreateReleaseOption,
 | 
			
		||||
    ) -> Result<Release, ForgejoError> {
 | 
			
		||||
        self.post(&format!("repos/{owner}/{repo}/releases"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn latest_release(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
    ) -> Result<Option<Release>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/releases/latest"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn download_zip_archive(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        target: &str,
 | 
			
		||||
    ) -> Result<Option<bytes::Bytes>, ForgejoError> {
 | 
			
		||||
        let request = self
 | 
			
		||||
            .client
 | 
			
		||||
            .get(
 | 
			
		||||
                self.url
 | 
			
		||||
                    .join(&format!("api/v1/repos/{owner}/{repo}/archive/{target}.zip"))
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            )
 | 
			
		||||
            .build()?;
 | 
			
		||||
        self.execute_opt_raw(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn download_tarball_archive(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        target: &str,
 | 
			
		||||
    ) -> Result<Option<bytes::Bytes>, ForgejoError> {
 | 
			
		||||
        let request = self
 | 
			
		||||
            .client
 | 
			
		||||
            .get(
 | 
			
		||||
                self.url
 | 
			
		||||
                    .join(&format!(
 | 
			
		||||
                        "api/v1/repos/{owner}/{repo}/archive/{target}.tar.gz"
 | 
			
		||||
                    ))
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
            )
 | 
			
		||||
            .build()?;
 | 
			
		||||
        self.execute_opt_raw(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn download_release_attachment(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        release: u64,
 | 
			
		||||
        attach: u64,
 | 
			
		||||
    ) -> Result<Option<bytes::Bytes>, ForgejoError> {
 | 
			
		||||
        let release = self
 | 
			
		||||
            .get_release_attachment(owner, repo, release, attach)
 | 
			
		||||
            .await?;
 | 
			
		||||
        let request = self.client.get(release.browser_download_url).build()?;
 | 
			
		||||
        self.execute_opt_raw(request).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_tags(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        query: TagQuery,
 | 
			
		||||
    ) -> Result<Vec<Tag>, ForgejoError> {
 | 
			
		||||
        self.get(&query.to_string(owner, repo)).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn create_tag(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        opts: CreateTagOption,
 | 
			
		||||
    ) -> Result<Tag, ForgejoError> {
 | 
			
		||||
        self.post(&format!("repos/{owner}/{repo}/tags"), &opts)
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn get_tag(
 | 
			
		||||
        &self,
 | 
			
		||||
        owner: &str,
 | 
			
		||||
        repo: &str,
 | 
			
		||||
        tag: &str,
 | 
			
		||||
    ) -> Result<Option<Tag>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("repos/{owner}/{repo}/tags/{tag}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn delete_tag(&self, owner: &str, repo: &str, tag: &str) -> Result<(), ForgejoError> {
 | 
			
		||||
        self.delete(&format!("repos/{owner}/{repo}/tags/{tag}"))
 | 
			
		||||
            .await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Repository {
 | 
			
		||||
    pub allow_merge_commits: bool,
 | 
			
		||||
    pub allow_rebase: bool,
 | 
			
		||||
    pub allow_rebase_explicit: bool,
 | 
			
		||||
    pub allow_rebase_update: bool,
 | 
			
		||||
    pub allow_squash_merge: bool,
 | 
			
		||||
    pub archived: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub archived_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    #[serde(deserialize_with = "crate::none_if_blank_url")]
 | 
			
		||||
    pub avatar_url: Option<Url>,
 | 
			
		||||
    pub clone_url: Url,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub default_allow_maintainer_edit: bool,
 | 
			
		||||
    pub default_branch: String,
 | 
			
		||||
    pub default_delete_branch_after_merge: bool,
 | 
			
		||||
    pub default_merge_style: String,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub empty: bool,
 | 
			
		||||
    pub external_tracker: Option<ExternalTracker>,
 | 
			
		||||
    pub external_wiki: Option<ExternalWiki>,
 | 
			
		||||
    pub fork: bool,
 | 
			
		||||
    pub forks_count: u64,
 | 
			
		||||
    pub full_name: String,
 | 
			
		||||
    pub has_actions: bool,
 | 
			
		||||
    pub has_issues: bool,
 | 
			
		||||
    pub has_packages: bool,
 | 
			
		||||
    pub has_projects: bool,
 | 
			
		||||
    pub has_pull_requests: bool,
 | 
			
		||||
    pub has_releases: bool,
 | 
			
		||||
    pub has_wiki: bool,
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub ignore_whitespace_conflicts: bool,
 | 
			
		||||
    pub internal: bool,
 | 
			
		||||
    pub internal_tracker: Option<InternalTracker>,
 | 
			
		||||
    pub language: String,
 | 
			
		||||
    pub languages_url: Url,
 | 
			
		||||
    pub link: String,
 | 
			
		||||
    pub mirror: bool,
 | 
			
		||||
    pub mirror_interval: Option<String>,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub mirror_updated: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub open_issues_count: u64,
 | 
			
		||||
    pub open_pr_counter: u64,
 | 
			
		||||
    #[serde(deserialize_with = "crate::none_if_blank_url")]
 | 
			
		||||
    pub original_url: Option<Url>,
 | 
			
		||||
    pub owner: User,
 | 
			
		||||
    pub parent: Option<Box<Repository>>,
 | 
			
		||||
    pub permissions: Permission,
 | 
			
		||||
    pub private: bool,
 | 
			
		||||
    pub release_counter: u64,
 | 
			
		||||
    pub repo_transfer: Option<RepoTransfer>,
 | 
			
		||||
    pub size: u64,
 | 
			
		||||
    pub ssh_url: String,
 | 
			
		||||
    pub stars_count: u64,
 | 
			
		||||
    pub template: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    pub watchers_count: u64,
 | 
			
		||||
    pub website: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct RepositoryMeta {
 | 
			
		||||
    pub full_name: String,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub owner: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CreateRepoOption {
 | 
			
		||||
    pub auto_init: bool,
 | 
			
		||||
    pub default_branch: String,
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub gitignores: String,
 | 
			
		||||
    pub issue_labels: String,
 | 
			
		||||
    pub license: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub private: bool,
 | 
			
		||||
    pub readme: String,
 | 
			
		||||
    pub template: bool,
 | 
			
		||||
    pub trust_model: TrustModel,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq)]
 | 
			
		||||
pub enum TrustModel {
 | 
			
		||||
    Default,
 | 
			
		||||
    Collaborator,
 | 
			
		||||
    Committer,
 | 
			
		||||
    #[serde(rename = "collaboratorcommiter")]
 | 
			
		||||
    CollaboratorCommitter,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Milestone {
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub closed_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub closed_issues: u64,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_on: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub open_issues: u64,
 | 
			
		||||
    pub state: State,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct PullRequest {
 | 
			
		||||
    pub allow_maintainer_edit: bool,
 | 
			
		||||
    pub assignee: User,
 | 
			
		||||
    pub assignees: Vec<User>,
 | 
			
		||||
    pub base: PrBranchInfo,
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub closed_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub comments: u64,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub diff_url: Url,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_date: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub head: PrBranchInfo,
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub is_locked: bool,
 | 
			
		||||
    pub labels: Vec<Label>,
 | 
			
		||||
    pub merge_base: String,
 | 
			
		||||
    pub merge_commit_sha: Option<String>,
 | 
			
		||||
    pub mergeable: bool,
 | 
			
		||||
    pub merged: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub merged_at: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub merged_by: Option<User>,
 | 
			
		||||
    pub milestone: Option<Milestone>,
 | 
			
		||||
    pub number: u64,
 | 
			
		||||
    pub patch_url: Url,
 | 
			
		||||
    pub pin_order: u64,
 | 
			
		||||
    pub requested_reviewers: Option<Vec<User>>,
 | 
			
		||||
    pub state: State,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub updated_at: time::OffsetDateTime,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    pub user: User,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct PrBranchInfo {
 | 
			
		||||
    pub label: String,
 | 
			
		||||
    #[serde(rename = "ref")]
 | 
			
		||||
    pub _ref: String,
 | 
			
		||||
    pub repo: Repository,
 | 
			
		||||
    pub repo_id: u64,
 | 
			
		||||
    pub sha: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct PullRequestMeta {
 | 
			
		||||
    pub merged: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub merged_at: Option<time::OffsetDateTime>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct PullQuery {
 | 
			
		||||
    pub state: Option<State>,
 | 
			
		||||
    pub sort: Option<PullQuerySort>,
 | 
			
		||||
    pub milestone: Option<u64>,
 | 
			
		||||
    pub labels: Vec<u64>,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PullQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str) -> String {
 | 
			
		||||
        use std::fmt::Write;
 | 
			
		||||
        // This is different to other query struct serialization because
 | 
			
		||||
        // `labels` is serialized so strangely
 | 
			
		||||
        let mut s = String::new();
 | 
			
		||||
        s.push_str("repos/");
 | 
			
		||||
        s.push_str(owner);
 | 
			
		||||
        s.push('/');
 | 
			
		||||
        s.push_str(repo);
 | 
			
		||||
        s.push_str("/pulls?");
 | 
			
		||||
        if let Some(state) = self.state {
 | 
			
		||||
            s.push_str("state=");
 | 
			
		||||
            s.push_str(state.as_str());
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(sort) = self.sort {
 | 
			
		||||
            s.push_str("sort=");
 | 
			
		||||
            s.push_str(sort.as_str());
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(milestone) = self.milestone {
 | 
			
		||||
            s.push_str("sort=");
 | 
			
		||||
            s.write_fmt(format_args!("{milestone}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        for label in &self.labels {
 | 
			
		||||
            s.push_str("labels=");
 | 
			
		||||
            s.write_fmt(format_args!("{label}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(page) = self.page {
 | 
			
		||||
            s.push_str("page=");
 | 
			
		||||
            s.write_fmt(format_args!("{page}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        if let Some(limit) = self.limit {
 | 
			
		||||
            s.push_str("limit=");
 | 
			
		||||
            s.write_fmt(format_args!("{limit}"))
 | 
			
		||||
                .expect("writing to a string never fails");
 | 
			
		||||
            s.push('&');
 | 
			
		||||
        }
 | 
			
		||||
        s
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Copy, Debug)]
 | 
			
		||||
pub enum PullQuerySort {
 | 
			
		||||
    Oldest,
 | 
			
		||||
    RecentUpdate,
 | 
			
		||||
    LeastUpdate,
 | 
			
		||||
    MostComment,
 | 
			
		||||
    LeastComment,
 | 
			
		||||
    Priority,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PullQuerySort {
 | 
			
		||||
    fn as_str(&self) -> &'static str {
 | 
			
		||||
        match self {
 | 
			
		||||
            PullQuerySort::Oldest => "oldest",
 | 
			
		||||
            PullQuerySort::RecentUpdate => "recentupdate",
 | 
			
		||||
            PullQuerySort::LeastUpdate => "leastupdate",
 | 
			
		||||
            PullQuerySort::MostComment => "mostcomment",
 | 
			
		||||
            PullQuerySort::LeastComment => "leastcomment",
 | 
			
		||||
            PullQuerySort::Priority => "priority",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct CreatePullRequestOption {
 | 
			
		||||
    pub assignee: Option<String>,
 | 
			
		||||
    pub assignees: Vec<String>,
 | 
			
		||||
    pub base: String,
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339::option")]
 | 
			
		||||
    pub due_date: Option<time::OffsetDateTime>,
 | 
			
		||||
    pub head: String,
 | 
			
		||||
    pub labels: Vec<u64>,
 | 
			
		||||
    pub milestone: Option<u64>,
 | 
			
		||||
    pub title: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct MergePullRequestOption {
 | 
			
		||||
    #[serde(rename = "Do")]
 | 
			
		||||
    pub act: MergePrAction,
 | 
			
		||||
    #[serde(rename = "MergeCommitId")]
 | 
			
		||||
    pub merge_commit_id: Option<String>,
 | 
			
		||||
    #[serde(rename = "MergeMessageField")]
 | 
			
		||||
    pub merge_message_field: Option<String>,
 | 
			
		||||
    #[serde(rename = "MergeTitleField")]
 | 
			
		||||
    pub merge_title_field: Option<String>,
 | 
			
		||||
    pub delete_branch_after_merge: Option<bool>,
 | 
			
		||||
    pub force_merge: Option<bool>,
 | 
			
		||||
    pub head_commit_id: Option<String>,
 | 
			
		||||
    pub merge_when_checks_succeed: Option<bool>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub enum MergePrAction {
 | 
			
		||||
    #[serde(rename = "merge")]
 | 
			
		||||
    #[default]
 | 
			
		||||
    Merge,
 | 
			
		||||
    #[serde(rename = "rebase")]
 | 
			
		||||
    Rebase,
 | 
			
		||||
    #[serde(rename = "rebase-merge")]
 | 
			
		||||
    RebaseMerge,
 | 
			
		||||
    #[serde(rename = "squash")]
 | 
			
		||||
    Squash,
 | 
			
		||||
    #[serde(rename = "manually-merged")]
 | 
			
		||||
    ManuallyMerged,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Release {
 | 
			
		||||
    pub assets: Vec<Attachment>,
 | 
			
		||||
    pub author: User,
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created_at: time::OffsetDateTime,
 | 
			
		||||
    pub draft: bool,
 | 
			
		||||
    pub html_url: Url,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub prerelease: bool,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub published_at: time::OffsetDateTime,
 | 
			
		||||
    pub tag_name: String,
 | 
			
		||||
    pub tarball_url: Url,
 | 
			
		||||
    pub target_commitish: String,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    pub zipball_url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct CreateReleaseOption {
 | 
			
		||||
    pub body: String,
 | 
			
		||||
    pub draft: bool,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub prerelease: bool,
 | 
			
		||||
    pub tag_name: String,
 | 
			
		||||
    pub target_commitish: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct EditReleaseOption {
 | 
			
		||||
    pub body: Option<String>,
 | 
			
		||||
    pub draft: Option<bool>,
 | 
			
		||||
    pub name: Option<String>,
 | 
			
		||||
    pub prerelease: Option<bool>,
 | 
			
		||||
    pub tag_name: Option<String>,
 | 
			
		||||
    pub target_commitish: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct ReleaseQuery {
 | 
			
		||||
    pub draft: Option<bool>,
 | 
			
		||||
    pub prerelease: Option<bool>,
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ReleaseQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str) -> String {
 | 
			
		||||
        format!(
 | 
			
		||||
            "repos/{owner}/{repo}/releases?draft={}&pre-release={}&page={}&limit={}",
 | 
			
		||||
            opt_bool_s(self.draft),
 | 
			
		||||
            opt_bool_s(self.prerelease),
 | 
			
		||||
            self.page.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
            self.limit.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn opt_bool_s(b: Option<bool>) -> &'static str {
 | 
			
		||||
    match b {
 | 
			
		||||
        Some(true) => "true",
 | 
			
		||||
        Some(false) => "false",
 | 
			
		||||
        None => "",
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Tag {
 | 
			
		||||
    pub commit: CommitMeta,
 | 
			
		||||
    pub id: String,
 | 
			
		||||
    pub message: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub tarball_url: Url,
 | 
			
		||||
    pub zipball_url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
 | 
			
		||||
pub struct CreateTagOption {
 | 
			
		||||
    pub message: Option<String>,
 | 
			
		||||
    pub tag_name: String,
 | 
			
		||||
    pub target: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct TagQuery {
 | 
			
		||||
    pub page: Option<u32>,
 | 
			
		||||
    pub limit: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TagQuery {
 | 
			
		||||
    fn to_string(&self, owner: &str, repo: &str) -> String {
 | 
			
		||||
        format!(
 | 
			
		||||
            "repos/{owner}/{repo}/tags?page={}&limit={}",
 | 
			
		||||
            self.page.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
            self.limit.map(|page| page.to_string()).unwrap_or_default(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct CommitMeta {
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created: time::OffsetDateTime,
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
    pub sha: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct ExternalTracker {
 | 
			
		||||
    #[serde(rename = "external_tracker_format")]
 | 
			
		||||
    pub format: String,
 | 
			
		||||
    #[serde(rename = "external_tracker_regexp_pattern")]
 | 
			
		||||
    pub regexp_pattern: String,
 | 
			
		||||
    #[serde(rename = "external_tracker_style")]
 | 
			
		||||
    pub style: String,
 | 
			
		||||
    #[serde(rename = "external_tracker_url")]
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct InternalTracker {
 | 
			
		||||
    pub allow_only_contributors_to_track_time: bool,
 | 
			
		||||
    pub enable_issue_dependencies: bool,
 | 
			
		||||
    pub enable_time_tracker: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct ExternalWiki {
 | 
			
		||||
    #[serde(rename = "external_wiki_url")]
 | 
			
		||||
    pub url: Url,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct Permission {
 | 
			
		||||
    pub admin: bool,
 | 
			
		||||
    pub pull: bool,
 | 
			
		||||
    pub push: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct RepoTransfer {
 | 
			
		||||
    pub doer: User,
 | 
			
		||||
    pub recipient: User,
 | 
			
		||||
    pub teams: Vec<Team>,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								src/user.rs
									
										
									
									
									
								
							
							
						
						
									
										59
									
								
								src/user.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,59 +0,0 @@
 | 
			
		|||
use super::*;
 | 
			
		||||
 | 
			
		||||
/// User operations.
 | 
			
		||||
impl Forgejo {
 | 
			
		||||
    /// Returns info about the authorized user.
 | 
			
		||||
    pub async fn myself(&self) -> Result<User, ForgejoError> {
 | 
			
		||||
        self.get("user").await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns info about the specified user.
 | 
			
		||||
    pub async fn get_user(&self, user: &str) -> Result<Option<User>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("users/{user}/")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets the list of users that follow the specified user.
 | 
			
		||||
    pub async fn get_followers(&self, user: &str) -> Result<Option<Vec<User>>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("users/{user}/followers/")).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets the list of users the specified user is following.
 | 
			
		||||
    pub async fn get_following(&self, user: &str) -> Result<Option<Vec<User>>, ForgejoError> {
 | 
			
		||||
        self.get_opt(&format!("users/{user}/following/")).await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub struct User {
 | 
			
		||||
    pub active: bool,
 | 
			
		||||
    pub avatar_url: Url,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub created: time::OffsetDateTime,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub email: String,
 | 
			
		||||
    pub followers_count: u64,
 | 
			
		||||
    pub following_count: u64,
 | 
			
		||||
    pub full_name: String,
 | 
			
		||||
    pub id: u64,
 | 
			
		||||
    pub is_admin: bool,
 | 
			
		||||
    pub language: String,
 | 
			
		||||
    #[serde(with = "time::serde::rfc3339")]
 | 
			
		||||
    pub last_login: time::OffsetDateTime,
 | 
			
		||||
    pub location: String,
 | 
			
		||||
    pub login: String,
 | 
			
		||||
    pub login_name: String,
 | 
			
		||||
    pub prohibit_login: bool,
 | 
			
		||||
    pub restricted: bool,
 | 
			
		||||
    pub starred_repos_count: u64,
 | 
			
		||||
    pub website: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize, Debug, PartialEq)]
 | 
			
		||||
pub enum UserVisibility {
 | 
			
		||||
    #[serde(rename = "public")]
 | 
			
		||||
    Public,
 | 
			
		||||
    #[serde(rename = "limited")]
 | 
			
		||||
    Limited,
 | 
			
		||||
    #[serde(rename = "private")]
 | 
			
		||||
    Private,
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue