forgejo_api/generated/
methods.rs

1use super::structs::*;
2use crate::ForgejoError;
3use std::collections::BTreeMap;
4
5impl crate::Forgejo {
6    /// Returns the instance's Actor
7    pub async fn activitypub_instance_actor(&self) -> Result<ActivityPub, ForgejoError> {
8        let request = self.get("activitypub/actor").build()?;
9        let response = self.execute(request).await?;
10        match response.status().as_u16() {
11            200 => Ok(response.json().await?),
12            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
13        }
14    }
15
16    /// Send to the inbox
17    pub async fn activitypub_instance_actor_inbox(&self) -> Result<(), ForgejoError> {
18        let request = self.post("activitypub/actor/inbox").build()?;
19        let response = self.execute(request).await?;
20        match response.status().as_u16() {
21            204 => Ok(()),
22            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
23        }
24    }
25
26    /// Returns the Repository actor for a repo
27    ///
28    /// - `repository-id`: repository ID of the repo
29    pub async fn activitypub_repository(
30        &self,
31        repository_id: u32,
32    ) -> Result<ActivityPub, ForgejoError> {
33        let request = self
34            .get(&format!("activitypub/repository-id/{repository_id}"))
35            .build()?;
36        let response = self.execute(request).await?;
37        match response.status().as_u16() {
38            200 => Ok(response.json().await?),
39            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
40        }
41    }
42
43    /// Send to the inbox
44    ///
45    /// - `repository-id`: repository ID of the repo
46    /// - `body`: See [`ForgeLike`]
47    pub async fn activitypub_repository_inbox(
48        &self,
49        repository_id: u32,
50        body: ForgeLike,
51    ) -> Result<(), ForgejoError> {
52        let request = self
53            .post(&format!("activitypub/repository-id/{repository_id}/inbox"))
54            .json(&body)
55            .build()?;
56        let response = self.execute(request).await?;
57        match response.status().as_u16() {
58            204 => Ok(()),
59            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
60        }
61    }
62
63    /// Returns the Person actor for a user
64    ///
65    /// - `user-id`: user ID of the user
66    pub async fn activitypub_person(&self, user_id: u32) -> Result<ActivityPub, ForgejoError> {
67        let request = self
68            .get(&format!("activitypub/user-id/{user_id}"))
69            .build()?;
70        let response = self.execute(request).await?;
71        match response.status().as_u16() {
72            200 => Ok(response.json().await?),
73            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
74        }
75    }
76
77    /// Send to the inbox
78    ///
79    /// - `user-id`: user ID of the user
80    pub async fn activitypub_person_inbox(&self, user_id: u32) -> Result<(), ForgejoError> {
81        let request = self
82            .post(&format!("activitypub/user-id/{user_id}/inbox"))
83            .build()?;
84        let response = self.execute(request).await?;
85        match response.status().as_u16() {
86            204 => Ok(()),
87            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
88        }
89    }
90
91    /// List cron tasks
92    ///
93    pub async fn admin_cron_list(
94        &self,
95        query: AdminCronListQuery,
96    ) -> Result<(CronListHeaders, Vec<Cron>), ForgejoError> {
97        let request = self.get(&format!("admin/cron?{query}")).build()?;
98        let response = self.execute(request).await?;
99        match response.status().as_u16() {
100            200 => Ok((response.headers().try_into()?, response.json().await?)),
101            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
102        }
103    }
104
105    /// Run cron task
106    ///
107    /// - `task`: task to run
108    pub async fn admin_cron_run(&self, task: &str) -> Result<(), ForgejoError> {
109        let request = self.post(&format!("admin/cron/{task}")).build()?;
110        let response = self.execute(request).await?;
111        match response.status().as_u16() {
112            204 => Ok(()),
113            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
114        }
115    }
116
117    /// List all emails
118    ///
119    pub async fn admin_get_all_emails(
120        &self,
121        query: AdminGetAllEmailsQuery,
122    ) -> Result<Vec<Email>, ForgejoError> {
123        let request = self.get(&format!("admin/emails?{query}")).build()?;
124        let response = self.execute(request).await?;
125        match response.status().as_u16() {
126            200 => Ok(response.json().await?),
127            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
128        }
129    }
130
131    /// Search all emails
132    ///
133    pub async fn admin_search_emails(
134        &self,
135        query: AdminSearchEmailsQuery,
136    ) -> Result<Vec<Email>, ForgejoError> {
137        let request = self.get(&format!("admin/emails/search?{query}")).build()?;
138        let response = self.execute(request).await?;
139        match response.status().as_u16() {
140            200 => Ok(response.json().await?),
141            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
142        }
143    }
144
145    /// List system's webhooks
146    ///
147    pub async fn admin_list_hooks(
148        &self,
149        query: AdminListHooksQuery,
150    ) -> Result<(HookListHeaders, Vec<Hook>), ForgejoError> {
151        let request = self.get(&format!("admin/hooks?{query}")).build()?;
152        let response = self.execute(request).await?;
153        match response.status().as_u16() {
154            200 => Ok((response.headers().try_into()?, response.json().await?)),
155            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
156        }
157    }
158
159    /// Create a hook
160    ///
161    /// - `body`: See [`CreateHookOption`]
162    pub async fn admin_create_hook(&self, body: CreateHookOption) -> Result<Hook, ForgejoError> {
163        let request = self.post("admin/hooks").json(&body).build()?;
164        let response = self.execute(request).await?;
165        match response.status().as_u16() {
166            201 => Ok(response.json().await?),
167            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
168        }
169    }
170
171    /// Get a hook
172    ///
173    /// - `id`: id of the hook to get
174    pub async fn admin_get_hook(&self, id: u64) -> Result<Hook, ForgejoError> {
175        let request = self.get(&format!("admin/hooks/{id}")).build()?;
176        let response = self.execute(request).await?;
177        match response.status().as_u16() {
178            200 => Ok(response.json().await?),
179            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
180        }
181    }
182
183    /// Delete a hook
184    ///
185    /// - `id`: id of the hook to delete
186    pub async fn admin_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
187        let request = self.delete(&format!("admin/hooks/{id}")).build()?;
188        let response = self.execute(request).await?;
189        match response.status().as_u16() {
190            204 => Ok(()),
191            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
192        }
193    }
194
195    /// Update a hook
196    ///
197    /// - `id`: id of the hook to update
198    /// - `body`: See [`EditHookOption`]
199    pub async fn admin_edit_hook(
200        &self,
201        id: u64,
202        body: EditHookOption,
203    ) -> Result<Hook, ForgejoError> {
204        let request = self
205            .patch(&format!("admin/hooks/{id}"))
206            .json(&body)
207            .build()?;
208        let response = self.execute(request).await?;
209        match response.status().as_u16() {
210            200 => Ok(response.json().await?),
211            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
212        }
213    }
214
215    /// List all organizations
216    ///
217    pub async fn admin_get_all_orgs(
218        &self,
219        query: AdminGetAllOrgsQuery,
220    ) -> Result<(OrganizationListHeaders, Vec<Organization>), ForgejoError> {
221        let request = self.get(&format!("admin/orgs?{query}")).build()?;
222        let response = self.execute(request).await?;
223        match response.status().as_u16() {
224            200 => Ok((response.headers().try_into()?, response.json().await?)),
225            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
226        }
227    }
228
229    /// List the available quota groups
230    pub async fn admin_list_quota_groups(
231        &self,
232    ) -> Result<(QuotaGroupListHeaders, Vec<QuotaGroup>), ForgejoError> {
233        let request = self.get("admin/quota/groups").build()?;
234        let response = self.execute(request).await?;
235        match response.status().as_u16() {
236            200 => Ok((response.headers().try_into()?, response.json().await?)),
237            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
238        }
239    }
240
241    /// Create a new quota group
242    ///
243    /// - `group`: Definition of the quota group
244
245    ///   See [`CreateQuotaGroupOptions`]
246    pub async fn admin_create_quota_group(
247        &self,
248        group: CreateQuotaGroupOptions,
249    ) -> Result<QuotaGroup, ForgejoError> {
250        let request = self.post("admin/quota/groups").json(&group).build()?;
251        let response = self.execute(request).await?;
252        match response.status().as_u16() {
253            201 => Ok(response.json().await?),
254            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
255        }
256    }
257
258    /// Get information about the quota group
259    ///
260    /// - `quotagroup`: quota group to query
261    pub async fn admin_get_quota_group(
262        &self,
263        quotagroup: &str,
264    ) -> Result<QuotaGroup, ForgejoError> {
265        let request = self
266            .get(&format!("admin/quota/groups/{quotagroup}"))
267            .build()?;
268        let response = self.execute(request).await?;
269        match response.status().as_u16() {
270            200 => Ok(response.json().await?),
271            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
272        }
273    }
274
275    /// Delete a quota group
276    ///
277    /// - `quotagroup`: quota group to delete
278    pub async fn admin_delete_quota_group(&self, quotagroup: &str) -> Result<(), ForgejoError> {
279        let request = self
280            .delete(&format!("admin/quota/groups/{quotagroup}"))
281            .build()?;
282        let response = self.execute(request).await?;
283        match response.status().as_u16() {
284            204 => Ok(()),
285            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
286        }
287    }
288
289    /// Adds a rule to a quota group
290    ///
291    /// - `quotagroup`: quota group to add a rule to
292    /// - `quotarule`: the name of the quota rule to add to the group
293    pub async fn admin_add_rule_to_quota_group(
294        &self,
295        quotagroup: &str,
296        quotarule: &str,
297    ) -> Result<(), ForgejoError> {
298        let request = self
299            .put(&format!(
300                "admin/quota/groups/{quotagroup}/rules/{quotarule}"
301            ))
302            .build()?;
303        let response = self.execute(request).await?;
304        match response.status().as_u16() {
305            204 => Ok(()),
306            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
307        }
308    }
309
310    /// Removes a rule from a quota group
311    ///
312    /// - `quotagroup`: quota group to remove a rule from
313    /// - `quotarule`: the name of the quota rule to remove from the group
314    pub async fn admin_remove_rule_from_quota_group(
315        &self,
316        quotagroup: &str,
317        quotarule: &str,
318    ) -> Result<(), ForgejoError> {
319        let request = self
320            .delete(&format!(
321                "admin/quota/groups/{quotagroup}/rules/{quotarule}"
322            ))
323            .build()?;
324        let response = self.execute(request).await?;
325        match response.status().as_u16() {
326            204 => Ok(()),
327            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
328        }
329    }
330
331    /// List users in a quota group
332    ///
333    /// - `quotagroup`: quota group to list members of
334    pub async fn admin_list_users_in_quota_group(
335        &self,
336        quotagroup: &str,
337    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
338        let request = self
339            .get(&format!("admin/quota/groups/{quotagroup}/users"))
340            .build()?;
341        let response = self.execute(request).await?;
342        match response.status().as_u16() {
343            200 => Ok((response.headers().try_into()?, response.json().await?)),
344            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
345        }
346    }
347
348    /// Add a user to a quota group
349    ///
350    /// - `quotagroup`: quota group to add the user to
351    /// - `username`: username of the user to add to the quota group
352    pub async fn admin_add_user_to_quota_group(
353        &self,
354        quotagroup: &str,
355        username: &str,
356    ) -> Result<(), ForgejoError> {
357        let request = self
358            .put(&format!("admin/quota/groups/{quotagroup}/users/{username}"))
359            .build()?;
360        let response = self.execute(request).await?;
361        match response.status().as_u16() {
362            204 => Ok(()),
363            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
364        }
365    }
366
367    /// Remove a user from a quota group
368    ///
369    /// - `quotagroup`: quota group to remove a user from
370    /// - `username`: username of the user to remove from the quota group
371    pub async fn admin_remove_user_from_quota_group(
372        &self,
373        quotagroup: &str,
374        username: &str,
375    ) -> Result<(), ForgejoError> {
376        let request = self
377            .delete(&format!("admin/quota/groups/{quotagroup}/users/{username}"))
378            .build()?;
379        let response = self.execute(request).await?;
380        match response.status().as_u16() {
381            204 => Ok(()),
382            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
383        }
384    }
385
386    /// List the available quota rules
387    pub async fn admin_list_quota_rules(
388        &self,
389    ) -> Result<(QuotaRuleInfoListHeaders, Vec<QuotaRuleInfo>), ForgejoError> {
390        let request = self.get("admin/quota/rules").build()?;
391        let response = self.execute(request).await?;
392        match response.status().as_u16() {
393            200 => Ok((response.headers().try_into()?, response.json().await?)),
394            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
395        }
396    }
397
398    /// Create a new quota rule
399    ///
400    /// - `rule`: Definition of the quota rule
401
402    ///   See [`CreateQuotaRuleOptions`]
403    pub async fn admin_create_quota_rule(
404        &self,
405        rule: CreateQuotaRuleOptions,
406    ) -> Result<QuotaRuleInfo, ForgejoError> {
407        let request = self.post("admin/quota/rules").json(&rule).build()?;
408        let response = self.execute(request).await?;
409        match response.status().as_u16() {
410            201 => Ok(response.json().await?),
411            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
412        }
413    }
414
415    /// Get information about a quota rule
416    ///
417    /// - `quotarule`: quota rule to query
418    pub async fn admin_get_quota_rule(
419        &self,
420        quotarule: &str,
421    ) -> Result<QuotaRuleInfo, ForgejoError> {
422        let request = self
423            .get(&format!("admin/quota/rules/{quotarule}"))
424            .build()?;
425        let response = self.execute(request).await?;
426        match response.status().as_u16() {
427            200 => Ok(response.json().await?),
428            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
429        }
430    }
431
432    /// Deletes a quota rule
433    ///
434    /// - `quotarule`: quota rule to delete
435    pub async fn admin_delete_quota_rule(&self, quotarule: &str) -> Result<(), ForgejoError> {
436        let request = self
437            .delete(&format!("admin/quota/rules/{quotarule}"))
438            .build()?;
439        let response = self.execute(request).await?;
440        match response.status().as_u16() {
441            204 => Ok(()),
442            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
443        }
444    }
445
446    /// Change an existing quota rule
447    ///
448    /// - `quotarule`: Quota rule to change
449    /// - `rule`: See [`EditQuotaRuleOptions`]
450    pub async fn admin_edit_quota_rule(
451        &self,
452        quotarule: &str,
453        rule: EditQuotaRuleOptions,
454    ) -> Result<QuotaRuleInfo, ForgejoError> {
455        let request = self
456            .patch(&format!("admin/quota/rules/{quotarule}"))
457            .json(&rule)
458            .build()?;
459        let response = self.execute(request).await?;
460        match response.status().as_u16() {
461            200 => Ok(response.json().await?),
462            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
463        }
464    }
465
466    /// Get an global actions runner registration token
467    pub async fn admin_get_runner_registration_token(
468        &self,
469    ) -> Result<RegistrationTokenHeaders, ForgejoError> {
470        let request = self.get("admin/runners/registration-token").build()?;
471        let response = self.execute(request).await?;
472        match response.status().as_u16() {
473            200 => Ok(response.headers().try_into()?),
474            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
475        }
476    }
477
478    /// List unadopted repositories
479    ///
480    pub async fn admin_unadopted_list(
481        &self,
482        query: AdminUnadoptedListQuery,
483    ) -> Result<Vec<String>, ForgejoError> {
484        let request = self.get(&format!("admin/unadopted?{query}")).build()?;
485        let response = self.execute(request).await?;
486        match response.status().as_u16() {
487            200 => Ok(response.json().await?),
488            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
489        }
490    }
491
492    /// Adopt unadopted files as a repository
493    ///
494    /// - `owner`: owner of the repo
495    /// - `repo`: name of the repo
496    pub async fn admin_adopt_repository(
497        &self,
498        owner: &str,
499        repo: &str,
500    ) -> Result<(), ForgejoError> {
501        let request = self
502            .post(&format!("admin/unadopted/{owner}/{repo}"))
503            .build()?;
504        let response = self.execute(request).await?;
505        match response.status().as_u16() {
506            204 => Ok(()),
507            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
508        }
509    }
510
511    /// Delete unadopted files
512    ///
513    /// - `owner`: owner of the repo
514    /// - `repo`: name of the repo
515    pub async fn admin_delete_unadopted_repository(
516        &self,
517        owner: &str,
518        repo: &str,
519    ) -> Result<(), ForgejoError> {
520        let request = self
521            .delete(&format!("admin/unadopted/{owner}/{repo}"))
522            .build()?;
523        let response = self.execute(request).await?;
524        match response.status().as_u16() {
525            204 => Ok(()),
526            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
527        }
528    }
529
530    /// Search users according filter conditions
531    ///
532    pub async fn admin_search_users(
533        &self,
534        query: AdminSearchUsersQuery,
535    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
536        let request = self.get(&format!("admin/users?{query}")).build()?;
537        let response = self.execute(request).await?;
538        match response.status().as_u16() {
539            200 => Ok((response.headers().try_into()?, response.json().await?)),
540            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
541        }
542    }
543
544    /// Create a user
545    ///
546    /// - `body`: See [`CreateUserOption`]
547    pub async fn admin_create_user(&self, body: CreateUserOption) -> Result<User, ForgejoError> {
548        let request = self.post("admin/users").json(&body).build()?;
549        let response = self.execute(request).await?;
550        match response.status().as_u16() {
551            201 => Ok(response.json().await?),
552            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
553        }
554    }
555
556    /// Delete a user
557    ///
558    /// - `username`: username of user to delete
559    pub async fn admin_delete_user(
560        &self,
561        username: &str,
562        query: AdminDeleteUserQuery,
563    ) -> Result<(), ForgejoError> {
564        let request = self
565            .delete(&format!("admin/users/{username}?{query}"))
566            .build()?;
567        let response = self.execute(request).await?;
568        match response.status().as_u16() {
569            204 => Ok(()),
570            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
571        }
572    }
573
574    /// Edit an existing user
575    ///
576    /// - `username`: username of user to edit
577    /// - `body`: See [`EditUserOption`]
578    pub async fn admin_edit_user(
579        &self,
580        username: &str,
581        body: EditUserOption,
582    ) -> Result<User, ForgejoError> {
583        let request = self
584            .patch(&format!("admin/users/{username}"))
585            .json(&body)
586            .build()?;
587        let response = self.execute(request).await?;
588        match response.status().as_u16() {
589            200 => Ok(response.json().await?),
590            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
591        }
592    }
593
594    /// Add a public key on behalf of a user
595    ///
596    /// - `username`: username of the user
597    /// - `key`: See [`CreateKeyOption`]
598    pub async fn admin_create_public_key(
599        &self,
600        username: &str,
601        key: CreateKeyOption,
602    ) -> Result<PublicKey, ForgejoError> {
603        let request = self
604            .post(&format!("admin/users/{username}/keys"))
605            .json(&key)
606            .build()?;
607        let response = self.execute(request).await?;
608        match response.status().as_u16() {
609            201 => Ok(response.json().await?),
610            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
611        }
612    }
613
614    /// Delete a user's public key
615    ///
616    /// - `username`: username of user
617    /// - `id`: id of the key to delete
618    pub async fn admin_delete_user_public_key(
619        &self,
620        username: &str,
621        id: u64,
622    ) -> Result<(), ForgejoError> {
623        let request = self
624            .delete(&format!("admin/users/{username}/keys/{id}"))
625            .build()?;
626        let response = self.execute(request).await?;
627        match response.status().as_u16() {
628            204 => Ok(()),
629            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
630        }
631    }
632
633    /// Create an organization
634    ///
635    /// - `username`: username of the user that will own the created organization
636    /// - `organization`: See [`CreateOrgOption`]
637    pub async fn admin_create_org(
638        &self,
639        username: &str,
640        organization: CreateOrgOption,
641    ) -> Result<Organization, ForgejoError> {
642        let request = self
643            .post(&format!("admin/users/{username}/orgs"))
644            .json(&organization)
645            .build()?;
646        let response = self.execute(request).await?;
647        match response.status().as_u16() {
648            201 => Ok(response.json().await?),
649            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
650        }
651    }
652
653    /// Get the user's quota info
654    ///
655    /// - `username`: username of user to query
656    pub async fn admin_get_user_quota(&self, username: &str) -> Result<QuotaInfo, ForgejoError> {
657        let request = self.get(&format!("admin/users/{username}/quota")).build()?;
658        let response = self.execute(request).await?;
659        match response.status().as_u16() {
660            200 => Ok(response.json().await?),
661            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
662        }
663    }
664
665    /// Set the user's quota groups to a given list.
666    ///
667    /// - `username`: username of the user to modify the quota groups from
668    /// - `groups`: list of groups that the user should be a member of
669
670    ///   See [`SetUserQuotaGroupsOptions`]
671    pub async fn admin_set_user_quota_groups(
672        &self,
673        username: &str,
674        groups: SetUserQuotaGroupsOptions,
675    ) -> Result<(), ForgejoError> {
676        let request = self
677            .post(&format!("admin/users/{username}/quota/groups"))
678            .json(&groups)
679            .build()?;
680        let response = self.execute(request).await?;
681        match response.status().as_u16() {
682            204 => Ok(()),
683            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
684        }
685    }
686
687    /// Rename a user
688    ///
689    /// - `username`: existing username of user
690    /// - `body`: See [`RenameUserOption`]
691    pub async fn admin_rename_user(
692        &self,
693        username: &str,
694        body: RenameUserOption,
695    ) -> Result<(), ForgejoError> {
696        let request = self
697            .post(&format!("admin/users/{username}/rename"))
698            .json(&body)
699            .build()?;
700        let response = self.execute(request).await?;
701        match response.status().as_u16() {
702            204 => Ok(()),
703            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
704        }
705    }
706
707    /// Create a repository on behalf of a user
708    ///
709    /// - `username`: username of the user. This user will own the created repository
710    /// - `repository`: See [`CreateRepoOption`]
711    pub async fn admin_create_repo(
712        &self,
713        username: &str,
714        repository: CreateRepoOption,
715    ) -> Result<Repository, ForgejoError> {
716        let request = self
717            .post(&format!("admin/users/{username}/repos"))
718            .json(&repository)
719            .build()?;
720        let response = self.execute(request).await?;
721        match response.status().as_u16() {
722            201 => Ok(response.json().await?),
723            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
724        }
725    }
726
727    /// Returns a list of all gitignore templates
728    pub async fn list_gitignores_templates(&self) -> Result<Vec<String>, ForgejoError> {
729        let request = self.get("gitignore/templates").build()?;
730        let response = self.execute(request).await?;
731        match response.status().as_u16() {
732            200 => Ok(response.json().await?),
733            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
734        }
735    }
736
737    /// Returns information about a gitignore template
738    ///
739    /// - `name`: name of the template
740    pub async fn get_gitignore_template_info(
741        &self,
742        name: &str,
743    ) -> Result<GitignoreTemplateInfo, ForgejoError> {
744        let request = self.get(&format!("gitignore/templates/{name}")).build()?;
745        let response = self.execute(request).await?;
746        match response.status().as_u16() {
747            200 => Ok(response.json().await?),
748            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
749        }
750    }
751
752    /// Returns a list of all label templates
753    pub async fn list_label_templates(&self) -> Result<Vec<String>, ForgejoError> {
754        let request = self.get("label/templates").build()?;
755        let response = self.execute(request).await?;
756        match response.status().as_u16() {
757            200 => Ok(response.json().await?),
758            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
759        }
760    }
761
762    /// Returns all labels in a template
763    ///
764    /// - `name`: name of the template
765    pub async fn get_label_template_info(
766        &self,
767        name: &str,
768    ) -> Result<Vec<LabelTemplate>, ForgejoError> {
769        let request = self.get(&format!("label/templates/{name}")).build()?;
770        let response = self.execute(request).await?;
771        match response.status().as_u16() {
772            200 => Ok(response.json().await?),
773            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
774        }
775    }
776
777    /// Returns a list of all license templates
778    pub async fn list_license_templates(
779        &self,
780    ) -> Result<Vec<LicensesTemplateListEntry>, ForgejoError> {
781        let request = self.get("licenses").build()?;
782        let response = self.execute(request).await?;
783        match response.status().as_u16() {
784            200 => Ok(response.json().await?),
785            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
786        }
787    }
788
789    /// Returns information about a license template
790    ///
791    /// - `name`: name of the license
792    pub async fn get_license_template_info(
793        &self,
794        name: &str,
795    ) -> Result<LicenseTemplateInfo, ForgejoError> {
796        let request = self.get(&format!("licenses/{name}")).build()?;
797        let response = self.execute(request).await?;
798        match response.status().as_u16() {
799            200 => Ok(response.json().await?),
800            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
801        }
802    }
803
804    /// Render a markdown document as HTML
805    ///
806    /// - `body`: See [`MarkdownOption`]
807    pub async fn render_markdown(&self, body: MarkdownOption) -> Result<String, ForgejoError> {
808        let request = self.post("markdown").json(&body).build()?;
809        let response = self.execute(request).await?;
810        match response.status().as_u16() {
811            200 => Ok(response.text().await?),
812            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
813        }
814    }
815
816    /// Render raw markdown as HTML
817    ///
818    /// - `body`: Request body to render
819
820    ///   See [`String`]
821    pub async fn render_markdown_raw(&self, body: String) -> Result<String, ForgejoError> {
822        let request = self.post("markdown/raw").body(body).build()?;
823        let response = self.execute(request).await?;
824        match response.status().as_u16() {
825            200 => Ok(response.text().await?),
826            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
827        }
828    }
829
830    /// Render a markup document as HTML
831    ///
832    /// - `body`: See [`MarkupOption`]
833    pub async fn render_markup(&self, body: MarkupOption) -> Result<String, ForgejoError> {
834        let request = self.post("markup").json(&body).build()?;
835        let response = self.execute(request).await?;
836        match response.status().as_u16() {
837            200 => Ok(response.text().await?),
838            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
839        }
840    }
841
842    /// Returns the nodeinfo of the Forgejo application
843    pub async fn get_node_info(&self) -> Result<NodeInfo, ForgejoError> {
844        let request = self.get("nodeinfo").build()?;
845        let response = self.execute(request).await?;
846        match response.status().as_u16() {
847            200 => Ok(response.json().await?),
848            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
849        }
850    }
851
852    /// List users's notification threads
853    ///
854    pub async fn notify_get_list(
855        &self,
856        query: NotifyGetListQuery,
857    ) -> Result<(NotificationThreadListHeaders, Vec<NotificationThread>), ForgejoError> {
858        let request = self.get(&format!("notifications?{query}")).build()?;
859        let response = self.execute(request).await?;
860        match response.status().as_u16() {
861            200 => Ok((response.headers().try_into()?, response.json().await?)),
862            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
863        }
864    }
865
866    /// Mark notification threads as read, pinned or unread
867    ///
868    pub async fn notify_read_list(
869        &self,
870        query: NotifyReadListQuery,
871    ) -> Result<(NotificationThreadListHeaders, Vec<NotificationThread>), ForgejoError> {
872        let request = self.put(&format!("notifications?{query}")).build()?;
873        let response = self.execute(request).await?;
874        match response.status().as_u16() {
875            205 => Ok((response.headers().try_into()?, response.json().await?)),
876            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
877        }
878    }
879
880    /// Check if unread notifications exist
881    pub async fn notify_new_available(&self) -> Result<NotificationCount, ForgejoError> {
882        let request = self.get("notifications/new").build()?;
883        let response = self.execute(request).await?;
884        match response.status().as_u16() {
885            200 => Ok(response.json().await?),
886            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
887        }
888    }
889
890    /// Get notification thread by ID
891    ///
892    /// - `id`: id of notification thread
893    pub async fn notify_get_thread(&self, id: &str) -> Result<NotificationThread, ForgejoError> {
894        let request = self.get(&format!("notifications/threads/{id}")).build()?;
895        let response = self.execute(request).await?;
896        match response.status().as_u16() {
897            200 => Ok(response.json().await?),
898            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
899        }
900    }
901
902    /// Mark notification thread as read by ID
903    ///
904    /// - `id`: id of notification thread
905    pub async fn notify_read_thread(
906        &self,
907        id: &str,
908        query: NotifyReadThreadQuery,
909    ) -> Result<NotificationThread, ForgejoError> {
910        let request = self
911            .patch(&format!("notifications/threads/{id}?{query}"))
912            .build()?;
913        let response = self.execute(request).await?;
914        match response.status().as_u16() {
915            205 => Ok(response.json().await?),
916            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
917        }
918    }
919
920    /// Create a repository in an organization
921    ///
922    /// - `org`: name of organization
923    /// - `body`: See [`CreateRepoOption`]
924    pub async fn create_org_repo_deprecated(
925        &self,
926        org: &str,
927        body: CreateRepoOption,
928    ) -> Result<Repository, ForgejoError> {
929        let request = self.post(&format!("org/{org}/repos")).json(&body).build()?;
930        let response = self.execute(request).await?;
931        match response.status().as_u16() {
932            201 => Ok(response.json().await?),
933            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
934        }
935    }
936
937    /// Get list of organizations
938    ///
939    pub async fn org_get_all(
940        &self,
941        query: OrgGetAllQuery,
942    ) -> Result<(OrganizationListHeaders, Vec<Organization>), ForgejoError> {
943        let request = self.get(&format!("orgs?{query}")).build()?;
944        let response = self.execute(request).await?;
945        match response.status().as_u16() {
946            200 => Ok((response.headers().try_into()?, response.json().await?)),
947            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
948        }
949    }
950
951    /// Create an organization
952    ///
953    /// - `organization`: See [`CreateOrgOption`]
954    pub async fn org_create(
955        &self,
956        organization: CreateOrgOption,
957    ) -> Result<Organization, ForgejoError> {
958        let request = self.post("orgs").json(&organization).build()?;
959        let response = self.execute(request).await?;
960        match response.status().as_u16() {
961            201 => Ok(response.json().await?),
962            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
963        }
964    }
965
966    /// Get an organization
967    ///
968    /// - `org`: name of the organization to get
969    pub async fn org_get(&self, org: &str) -> Result<Organization, ForgejoError> {
970        let request = self.get(&format!("orgs/{org}")).build()?;
971        let response = self.execute(request).await?;
972        match response.status().as_u16() {
973            200 => Ok(response.json().await?),
974            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
975        }
976    }
977
978    /// Delete an organization
979    ///
980    /// - `org`: organization that is to be deleted
981    pub async fn org_delete(&self, org: &str) -> Result<(), ForgejoError> {
982        let request = self.delete(&format!("orgs/{org}")).build()?;
983        let response = self.execute(request).await?;
984        match response.status().as_u16() {
985            204 => Ok(()),
986            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
987        }
988    }
989
990    /// Edit an organization
991    ///
992    /// - `org`: name of the organization to edit
993    /// - `body`: See [`EditOrgOption`]
994    pub async fn org_edit(
995        &self,
996        org: &str,
997        body: EditOrgOption,
998    ) -> Result<Organization, ForgejoError> {
999        let request = self.patch(&format!("orgs/{org}")).json(&body).build()?;
1000        let response = self.execute(request).await?;
1001        match response.status().as_u16() {
1002            200 => Ok(response.json().await?),
1003            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1004        }
1005    }
1006
1007    /// Get an organization's actions runner registration token
1008    ///
1009    /// - `org`: name of the organization
1010    pub async fn org_get_runner_registration_token(
1011        &self,
1012        org: &str,
1013    ) -> Result<RegistrationTokenHeaders, ForgejoError> {
1014        let request = self
1015            .get(&format!("orgs/{org}/actions/runners/registration-token"))
1016            .build()?;
1017        let response = self.execute(request).await?;
1018        match response.status().as_u16() {
1019            200 => Ok(response.headers().try_into()?),
1020            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1021        }
1022    }
1023
1024    /// List an organization's actions secrets
1025    ///
1026    /// - `org`: name of the organization
1027    pub async fn org_list_actions_secrets(
1028        &self,
1029        org: &str,
1030        query: OrgListActionsSecretsQuery,
1031    ) -> Result<(SecretListHeaders, Vec<Secret>), ForgejoError> {
1032        let request = self
1033            .get(&format!("orgs/{org}/actions/secrets?{query}"))
1034            .build()?;
1035        let response = self.execute(request).await?;
1036        match response.status().as_u16() {
1037            200 => Ok((response.headers().try_into()?, response.json().await?)),
1038            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1039        }
1040    }
1041
1042    /// Create or Update a secret value in an organization
1043    ///
1044    /// - `org`: name of organization
1045    /// - `secretname`: name of the secret
1046    /// - `body`: See [`CreateOrUpdateSecretOption`]
1047    pub async fn update_org_secret(
1048        &self,
1049        org: &str,
1050        secretname: &str,
1051        body: CreateOrUpdateSecretOption,
1052    ) -> Result<(), ForgejoError> {
1053        let request = self
1054            .put(&format!("orgs/{org}/actions/secrets/{secretname}"))
1055            .json(&body)
1056            .build()?;
1057        let response = self.execute(request).await?;
1058        match response.status().as_u16() {
1059            201 => Ok(()),
1060            204 => Ok(()),
1061            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1062        }
1063    }
1064
1065    /// Delete a secret in an organization
1066    ///
1067    /// - `org`: name of organization
1068    /// - `secretname`: name of the secret
1069    pub async fn delete_org_secret(&self, org: &str, secretname: &str) -> Result<(), ForgejoError> {
1070        let request = self
1071            .delete(&format!("orgs/{org}/actions/secrets/{secretname}"))
1072            .build()?;
1073        let response = self.execute(request).await?;
1074        match response.status().as_u16() {
1075            204 => Ok(()),
1076            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1077        }
1078    }
1079
1080    /// Get an org-level variables list
1081    ///
1082    /// - `org`: name of the organization
1083    pub async fn get_org_variables_list(
1084        &self,
1085        org: &str,
1086        query: GetOrgVariablesListQuery,
1087    ) -> Result<(VariableListHeaders, Vec<ActionVariable>), ForgejoError> {
1088        let request = self
1089            .get(&format!("orgs/{org}/actions/variables?{query}"))
1090            .build()?;
1091        let response = self.execute(request).await?;
1092        match response.status().as_u16() {
1093            200 => Ok((response.headers().try_into()?, response.json().await?)),
1094            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1095        }
1096    }
1097
1098    /// Get an org-level variable
1099    ///
1100    /// - `org`: name of the organization
1101    /// - `variablename`: name of the variable
1102    pub async fn get_org_variable(
1103        &self,
1104        org: &str,
1105        variablename: &str,
1106    ) -> Result<ActionVariable, ForgejoError> {
1107        let request = self
1108            .get(&format!("orgs/{org}/actions/variables/{variablename}"))
1109            .build()?;
1110        let response = self.execute(request).await?;
1111        match response.status().as_u16() {
1112            200 => Ok(response.json().await?),
1113            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1114        }
1115    }
1116
1117    /// Update an org-level variable
1118    ///
1119    /// - `org`: name of the organization
1120    /// - `variablename`: name of the variable
1121    /// - `body`: See [`UpdateVariableOption`]
1122    pub async fn update_org_variable(
1123        &self,
1124        org: &str,
1125        variablename: &str,
1126        body: UpdateVariableOption,
1127    ) -> Result<(), ForgejoError> {
1128        let request = self
1129            .put(&format!("orgs/{org}/actions/variables/{variablename}"))
1130            .json(&body)
1131            .build()?;
1132        let response = self.execute(request).await?;
1133        match response.status().as_u16() {
1134            201 => Ok(()),
1135            204 => Ok(()),
1136            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1137        }
1138    }
1139
1140    /// Create an org-level variable
1141    ///
1142    /// - `org`: name of the organization
1143    /// - `variablename`: name of the variable
1144    /// - `body`: See [`CreateVariableOption`]
1145    pub async fn create_org_variable(
1146        &self,
1147        org: &str,
1148        variablename: &str,
1149        body: CreateVariableOption,
1150    ) -> Result<(), ForgejoError> {
1151        let request = self
1152            .post(&format!("orgs/{org}/actions/variables/{variablename}"))
1153            .json(&body)
1154            .build()?;
1155        let response = self.execute(request).await?;
1156        match response.status().as_u16() {
1157            201 => Ok(()),
1158            204 => Ok(()),
1159            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1160        }
1161    }
1162
1163    /// Delete an org-level variable
1164    ///
1165    /// - `org`: name of the organization
1166    /// - `variablename`: name of the variable
1167    pub async fn delete_org_variable(
1168        &self,
1169        org: &str,
1170        variablename: &str,
1171    ) -> Result<Option<ActionVariable>, ForgejoError> {
1172        let request = self
1173            .delete(&format!("orgs/{org}/actions/variables/{variablename}"))
1174            .build()?;
1175        let response = self.execute(request).await?;
1176        match response.status().as_u16() {
1177            200 => Ok(Some(response.json().await?)),
1178            201 => Ok(None),
1179            204 => Ok(None),
1180            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1181        }
1182    }
1183
1184    /// List an organization's activity feeds
1185    ///
1186    /// - `org`: name of the org
1187    pub async fn org_list_activity_feeds(
1188        &self,
1189        org: &str,
1190        query: OrgListActivityFeedsQuery,
1191    ) -> Result<(ActivityFeedsListHeaders, Vec<Activity>), ForgejoError> {
1192        let request = self
1193            .get(&format!("orgs/{org}/activities/feeds?{query}"))
1194            .build()?;
1195        let response = self.execute(request).await?;
1196        match response.status().as_u16() {
1197            200 => Ok((response.headers().try_into()?, response.json().await?)),
1198            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1199        }
1200    }
1201
1202    /// Update Avatar
1203    ///
1204    /// - `org`: name of the organization
1205    /// - `body`: See [`UpdateUserAvatarOption`]
1206    pub async fn org_update_avatar(
1207        &self,
1208        org: &str,
1209        body: UpdateUserAvatarOption,
1210    ) -> Result<(), ForgejoError> {
1211        let request = self
1212            .post(&format!("orgs/{org}/avatar"))
1213            .json(&body)
1214            .build()?;
1215        let response = self.execute(request).await?;
1216        match response.status().as_u16() {
1217            204 => Ok(()),
1218            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1219        }
1220    }
1221
1222    /// Delete Avatar
1223    ///
1224    /// - `org`: name of the organization
1225    pub async fn org_delete_avatar(&self, org: &str) -> Result<(), ForgejoError> {
1226        let request = self.delete(&format!("orgs/{org}/avatar")).build()?;
1227        let response = self.execute(request).await?;
1228        match response.status().as_u16() {
1229            204 => Ok(()),
1230            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1231        }
1232    }
1233
1234    /// Blocks a user from the organization
1235    ///
1236    /// - `org`: name of the org
1237    /// - `username`: username of the user
1238    pub async fn org_block_user(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
1239        let request = self.put(&format!("orgs/{org}/block/{username}")).build()?;
1240        let response = self.execute(request).await?;
1241        match response.status().as_u16() {
1242            204 => Ok(()),
1243            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1244        }
1245    }
1246
1247    /// List an organization's webhooks
1248    ///
1249    /// - `org`: name of the organization
1250    pub async fn org_list_hooks(
1251        &self,
1252        org: &str,
1253        query: OrgListHooksQuery,
1254    ) -> Result<(HookListHeaders, Vec<Hook>), ForgejoError> {
1255        let request = self.get(&format!("orgs/{org}/hooks?{query}")).build()?;
1256        let response = self.execute(request).await?;
1257        match response.status().as_u16() {
1258            200 => Ok((response.headers().try_into()?, response.json().await?)),
1259            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1260        }
1261    }
1262
1263    /// Create a hook
1264    ///
1265    /// - `org`: name of the organization
1266    /// - `body`: See [`CreateHookOption`]
1267    pub async fn org_create_hook(
1268        &self,
1269        org: &str,
1270        body: CreateHookOption,
1271    ) -> Result<Hook, ForgejoError> {
1272        let request = self
1273            .post(&format!("orgs/{org}/hooks"))
1274            .json(&body)
1275            .build()?;
1276        let response = self.execute(request).await?;
1277        match response.status().as_u16() {
1278            201 => Ok(response.json().await?),
1279            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1280        }
1281    }
1282
1283    /// Get a hook
1284    ///
1285    /// - `org`: name of the organization
1286    /// - `id`: id of the hook to get
1287    pub async fn org_get_hook(&self, org: &str, id: u64) -> Result<Hook, ForgejoError> {
1288        let request = self.get(&format!("orgs/{org}/hooks/{id}")).build()?;
1289        let response = self.execute(request).await?;
1290        match response.status().as_u16() {
1291            200 => Ok(response.json().await?),
1292            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1293        }
1294    }
1295
1296    /// Delete a hook
1297    ///
1298    /// - `org`: name of the organization
1299    /// - `id`: id of the hook to delete
1300    pub async fn org_delete_hook(&self, org: &str, id: u64) -> Result<(), ForgejoError> {
1301        let request = self.delete(&format!("orgs/{org}/hooks/{id}")).build()?;
1302        let response = self.execute(request).await?;
1303        match response.status().as_u16() {
1304            204 => Ok(()),
1305            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1306        }
1307    }
1308
1309    /// Update a hook
1310    ///
1311    /// - `org`: name of the organization
1312    /// - `id`: id of the hook to update
1313    /// - `body`: See [`EditHookOption`]
1314    pub async fn org_edit_hook(
1315        &self,
1316        org: &str,
1317        id: u64,
1318        body: EditHookOption,
1319    ) -> Result<Hook, ForgejoError> {
1320        let request = self
1321            .patch(&format!("orgs/{org}/hooks/{id}"))
1322            .json(&body)
1323            .build()?;
1324        let response = self.execute(request).await?;
1325        match response.status().as_u16() {
1326            200 => Ok(response.json().await?),
1327            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1328        }
1329    }
1330
1331    /// List an organization's labels
1332    ///
1333    /// - `org`: name of the organization
1334    pub async fn org_list_labels(
1335        &self,
1336        org: &str,
1337        query: OrgListLabelsQuery,
1338    ) -> Result<(LabelListHeaders, Vec<Label>), ForgejoError> {
1339        let request = self.get(&format!("orgs/{org}/labels?{query}")).build()?;
1340        let response = self.execute(request).await?;
1341        match response.status().as_u16() {
1342            200 => Ok((response.headers().try_into()?, response.json().await?)),
1343            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1344        }
1345    }
1346
1347    /// Create a label for an organization
1348    ///
1349    /// - `org`: name of the organization
1350    /// - `body`: See [`CreateLabelOption`]
1351    pub async fn org_create_label(
1352        &self,
1353        org: &str,
1354        body: CreateLabelOption,
1355    ) -> Result<Label, ForgejoError> {
1356        let request = self
1357            .post(&format!("orgs/{org}/labels"))
1358            .json(&body)
1359            .build()?;
1360        let response = self.execute(request).await?;
1361        match response.status().as_u16() {
1362            201 => Ok(response.json().await?),
1363            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1364        }
1365    }
1366
1367    /// Get a single label
1368    ///
1369    /// - `org`: name of the organization
1370    /// - `id`: id of the label to get
1371    pub async fn org_get_label(&self, org: &str, id: u64) -> Result<Label, ForgejoError> {
1372        let request = self.get(&format!("orgs/{org}/labels/{id}")).build()?;
1373        let response = self.execute(request).await?;
1374        match response.status().as_u16() {
1375            200 => Ok(response.json().await?),
1376            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1377        }
1378    }
1379
1380    /// Delete a label
1381    ///
1382    /// - `org`: name of the organization
1383    /// - `id`: id of the label to delete
1384    pub async fn org_delete_label(&self, org: &str, id: u64) -> Result<(), ForgejoError> {
1385        let request = self.delete(&format!("orgs/{org}/labels/{id}")).build()?;
1386        let response = self.execute(request).await?;
1387        match response.status().as_u16() {
1388            204 => Ok(()),
1389            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1390        }
1391    }
1392
1393    /// Update a label
1394    ///
1395    /// - `org`: name of the organization
1396    /// - `id`: id of the label to edit
1397    /// - `body`: See [`EditLabelOption`]
1398    pub async fn org_edit_label(
1399        &self,
1400        org: &str,
1401        id: u64,
1402        body: EditLabelOption,
1403    ) -> Result<Label, ForgejoError> {
1404        let request = self
1405            .patch(&format!("orgs/{org}/labels/{id}"))
1406            .json(&body)
1407            .build()?;
1408        let response = self.execute(request).await?;
1409        match response.status().as_u16() {
1410            200 => Ok(response.json().await?),
1411            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1412        }
1413    }
1414
1415    /// List the organization's blocked users
1416    ///
1417    /// - `org`: name of the org
1418    pub async fn org_list_blocked_users(
1419        &self,
1420        org: &str,
1421        query: OrgListBlockedUsersQuery,
1422    ) -> Result<(BlockedUserListHeaders, Vec<BlockedUser>), ForgejoError> {
1423        let request = self
1424            .get(&format!("orgs/{org}/list_blocked?{query}"))
1425            .build()?;
1426        let response = self.execute(request).await?;
1427        match response.status().as_u16() {
1428            200 => Ok((response.headers().try_into()?, response.json().await?)),
1429            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1430        }
1431    }
1432
1433    /// List an organization's members
1434    ///
1435    /// - `org`: name of the organization
1436    pub async fn org_list_members(
1437        &self,
1438        org: &str,
1439        query: OrgListMembersQuery,
1440    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
1441        let request = self.get(&format!("orgs/{org}/members?{query}")).build()?;
1442        let response = self.execute(request).await?;
1443        match response.status().as_u16() {
1444            200 => Ok((response.headers().try_into()?, response.json().await?)),
1445            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1446        }
1447    }
1448
1449    /// Check if a user is a member of an organization
1450    ///
1451    /// - `org`: name of the organization
1452    /// - `username`: username of the user
1453    pub async fn org_is_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
1454        let request = self
1455            .get(&format!("orgs/{org}/members/{username}"))
1456            .build()?;
1457        let response = self.execute(request).await?;
1458        match response.status().as_u16() {
1459            204 => Ok(()),
1460            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1461        }
1462    }
1463
1464    /// Remove a member from an organization
1465    ///
1466    /// - `org`: name of the organization
1467    /// - `username`: username of the user
1468    pub async fn org_delete_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
1469        let request = self
1470            .delete(&format!("orgs/{org}/members/{username}"))
1471            .build()?;
1472        let response = self.execute(request).await?;
1473        match response.status().as_u16() {
1474            204 => Ok(()),
1475            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1476        }
1477    }
1478
1479    /// List an organization's public members
1480    ///
1481    /// - `org`: name of the organization
1482    pub async fn org_list_public_members(
1483        &self,
1484        org: &str,
1485        query: OrgListPublicMembersQuery,
1486    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
1487        let request = self
1488            .get(&format!("orgs/{org}/public_members?{query}"))
1489            .build()?;
1490        let response = self.execute(request).await?;
1491        match response.status().as_u16() {
1492            200 => Ok((response.headers().try_into()?, response.json().await?)),
1493            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1494        }
1495    }
1496
1497    /// Check if a user is a public member of an organization
1498    ///
1499    /// - `org`: name of the organization
1500    /// - `username`: username of the user
1501    pub async fn org_is_public_member(
1502        &self,
1503        org: &str,
1504        username: &str,
1505    ) -> Result<(), ForgejoError> {
1506        let request = self
1507            .get(&format!("orgs/{org}/public_members/{username}"))
1508            .build()?;
1509        let response = self.execute(request).await?;
1510        match response.status().as_u16() {
1511            204 => Ok(()),
1512            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1513        }
1514    }
1515
1516    /// Publicize a user's membership
1517    ///
1518    /// - `org`: name of the organization
1519    /// - `username`: username of the user
1520    pub async fn org_publicize_member(
1521        &self,
1522        org: &str,
1523        username: &str,
1524    ) -> Result<(), ForgejoError> {
1525        let request = self
1526            .put(&format!("orgs/{org}/public_members/{username}"))
1527            .build()?;
1528        let response = self.execute(request).await?;
1529        match response.status().as_u16() {
1530            204 => Ok(()),
1531            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1532        }
1533    }
1534
1535    /// Conceal a user's membership
1536    ///
1537    /// - `org`: name of the organization
1538    /// - `username`: username of the user
1539    pub async fn org_conceal_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
1540        let request = self
1541            .delete(&format!("orgs/{org}/public_members/{username}"))
1542            .build()?;
1543        let response = self.execute(request).await?;
1544        match response.status().as_u16() {
1545            204 => Ok(()),
1546            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1547        }
1548    }
1549
1550    /// Get quota information for an organization
1551    ///
1552    /// - `org`: name of the organization
1553    pub async fn org_get_quota(&self, org: &str) -> Result<QuotaInfo, ForgejoError> {
1554        let request = self.get(&format!("orgs/{org}/quota")).build()?;
1555        let response = self.execute(request).await?;
1556        match response.status().as_u16() {
1557            200 => Ok(response.json().await?),
1558            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1559        }
1560    }
1561
1562    /// List the artifacts affecting the organization's quota
1563    ///
1564    /// - `org`: name of the organization
1565    pub async fn org_list_quota_artifacts(
1566        &self,
1567        org: &str,
1568        query: OrgListQuotaArtifactsQuery,
1569    ) -> Result<(QuotaUsedArtifactListHeaders, Vec<QuotaUsedArtifact>), ForgejoError> {
1570        let request = self
1571            .get(&format!("orgs/{org}/quota/artifacts?{query}"))
1572            .build()?;
1573        let response = self.execute(request).await?;
1574        match response.status().as_u16() {
1575            200 => Ok((response.headers().try_into()?, response.json().await?)),
1576            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1577        }
1578    }
1579
1580    /// List the attachments affecting the organization's quota
1581    ///
1582    /// - `org`: name of the organization
1583    pub async fn org_list_quota_attachments(
1584        &self,
1585        org: &str,
1586        query: OrgListQuotaAttachmentsQuery,
1587    ) -> Result<(QuotaUsedAttachmentListHeaders, Vec<QuotaUsedAttachment>), ForgejoError> {
1588        let request = self
1589            .get(&format!("orgs/{org}/quota/attachments?{query}"))
1590            .build()?;
1591        let response = self.execute(request).await?;
1592        match response.status().as_u16() {
1593            200 => Ok((response.headers().try_into()?, response.json().await?)),
1594            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1595        }
1596    }
1597
1598    /// Check if the organization is over quota for a given subject
1599    ///
1600    /// - `org`: name of the organization
1601    pub async fn org_check_quota(&self, org: &str) -> Result<(), ForgejoError> {
1602        let request = self.get(&format!("orgs/{org}/quota/check")).build()?;
1603        let response = self.execute(request).await?;
1604        match response.status().as_u16() {
1605            200 => Ok(()),
1606            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1607        }
1608    }
1609
1610    /// List the packages affecting the organization's quota
1611    ///
1612    /// - `org`: name of the organization
1613    pub async fn org_list_quota_packages(
1614        &self,
1615        org: &str,
1616        query: OrgListQuotaPackagesQuery,
1617    ) -> Result<(QuotaUsedPackageListHeaders, Vec<QuotaUsedPackage>), ForgejoError> {
1618        let request = self
1619            .get(&format!("orgs/{org}/quota/packages?{query}"))
1620            .build()?;
1621        let response = self.execute(request).await?;
1622        match response.status().as_u16() {
1623            200 => Ok((response.headers().try_into()?, response.json().await?)),
1624            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1625        }
1626    }
1627
1628    /// List an organization's repos
1629    ///
1630    /// - `org`: name of the organization
1631    pub async fn org_list_repos(
1632        &self,
1633        org: &str,
1634        query: OrgListReposQuery,
1635    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
1636        let request = self.get(&format!("orgs/{org}/repos?{query}")).build()?;
1637        let response = self.execute(request).await?;
1638        match response.status().as_u16() {
1639            200 => Ok((response.headers().try_into()?, response.json().await?)),
1640            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1641        }
1642    }
1643
1644    /// Create a repository in an organization
1645    ///
1646    /// - `org`: name of organization
1647    /// - `body`: See [`CreateRepoOption`]
1648    pub async fn create_org_repo(
1649        &self,
1650        org: &str,
1651        body: CreateRepoOption,
1652    ) -> Result<Repository, ForgejoError> {
1653        let request = self
1654            .post(&format!("orgs/{org}/repos"))
1655            .json(&body)
1656            .build()?;
1657        let response = self.execute(request).await?;
1658        match response.status().as_u16() {
1659            201 => Ok(response.json().await?),
1660            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1661        }
1662    }
1663
1664    /// List an organization's teams
1665    ///
1666    /// - `org`: name of the organization
1667    pub async fn org_list_teams(
1668        &self,
1669        org: &str,
1670        query: OrgListTeamsQuery,
1671    ) -> Result<(TeamListHeaders, Vec<Team>), ForgejoError> {
1672        let request = self.get(&format!("orgs/{org}/teams?{query}")).build()?;
1673        let response = self.execute(request).await?;
1674        match response.status().as_u16() {
1675            200 => Ok((response.headers().try_into()?, response.json().await?)),
1676            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1677        }
1678    }
1679
1680    /// Create a team
1681    ///
1682    /// - `org`: name of the organization
1683    /// - `body`: See [`CreateTeamOption`]
1684    pub async fn org_create_team(
1685        &self,
1686        org: &str,
1687        body: CreateTeamOption,
1688    ) -> Result<Team, ForgejoError> {
1689        let request = self
1690            .post(&format!("orgs/{org}/teams"))
1691            .json(&body)
1692            .build()?;
1693        let response = self.execute(request).await?;
1694        match response.status().as_u16() {
1695            201 => Ok(response.json().await?),
1696            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1697        }
1698    }
1699
1700    /// Search for teams within an organization
1701    ///
1702    /// - `org`: name of the organization
1703    pub async fn team_search(
1704        &self,
1705        org: &str,
1706        query: TeamSearchQuery,
1707    ) -> Result<TeamSearchResponse, ForgejoError> {
1708        let request = self
1709            .get(&format!("orgs/{org}/teams/search?{query}"))
1710            .build()?;
1711        let response = self.execute(request).await?;
1712        match response.status().as_u16() {
1713            200 => Ok(response.json().await?),
1714            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1715        }
1716    }
1717
1718    /// Unblock a user from the organization
1719    ///
1720    /// - `org`: name of the org
1721    /// - `username`: username of the user
1722    pub async fn org_unblock_user(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
1723        let request = self
1724            .put(&format!("orgs/{org}/unblock/{username}"))
1725            .build()?;
1726        let response = self.execute(request).await?;
1727        match response.status().as_u16() {
1728            204 => Ok(()),
1729            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1730        }
1731    }
1732
1733    /// Gets all packages of an owner
1734    ///
1735    /// - `owner`: owner of the packages
1736    pub async fn list_packages(
1737        &self,
1738        owner: &str,
1739        query: ListPackagesQuery,
1740    ) -> Result<(PackageListHeaders, Vec<Package>), ForgejoError> {
1741        let request = self.get(&format!("packages/{owner}?{query}")).build()?;
1742        let response = self.execute(request).await?;
1743        match response.status().as_u16() {
1744            200 => Ok((response.headers().try_into()?, response.json().await?)),
1745            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1746        }
1747    }
1748
1749    /// Gets a package
1750    ///
1751    /// - `owner`: owner of the package
1752    /// - `type`: type of the package
1753    /// - `name`: name of the package
1754    /// - `version`: version of the package
1755    pub async fn get_package(
1756        &self,
1757        owner: &str,
1758        r#type: &str,
1759        name: &str,
1760        version: &str,
1761    ) -> Result<Package, ForgejoError> {
1762        let request = self
1763            .get(&format!("packages/{owner}/{type}/{name}/{version}"))
1764            .build()?;
1765        let response = self.execute(request).await?;
1766        match response.status().as_u16() {
1767            200 => Ok(response.json().await?),
1768            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1769        }
1770    }
1771
1772    /// Delete a package
1773    ///
1774    /// - `owner`: owner of the package
1775    /// - `type`: type of the package
1776    /// - `name`: name of the package
1777    /// - `version`: version of the package
1778    pub async fn delete_package(
1779        &self,
1780        owner: &str,
1781        r#type: &str,
1782        name: &str,
1783        version: &str,
1784    ) -> Result<(), ForgejoError> {
1785        let request = self
1786            .delete(&format!("packages/{owner}/{type}/{name}/{version}"))
1787            .build()?;
1788        let response = self.execute(request).await?;
1789        match response.status().as_u16() {
1790            204 => Ok(()),
1791            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1792        }
1793    }
1794
1795    /// Gets all files of a package
1796    ///
1797    /// - `owner`: owner of the package
1798    /// - `type`: type of the package
1799    /// - `name`: name of the package
1800    /// - `version`: version of the package
1801    pub async fn list_package_files(
1802        &self,
1803        owner: &str,
1804        r#type: &str,
1805        name: &str,
1806        version: &str,
1807    ) -> Result<(PackageFileListHeaders, Vec<PackageFile>), ForgejoError> {
1808        let request = self
1809            .get(&format!("packages/{owner}/{type}/{name}/{version}/files"))
1810            .build()?;
1811        let response = self.execute(request).await?;
1812        match response.status().as_u16() {
1813            200 => Ok((response.headers().try_into()?, response.json().await?)),
1814            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1815        }
1816    }
1817
1818    /// Search for issues across the repositories that the user has access to
1819    ///
1820    pub async fn issue_search_issues(
1821        &self,
1822        query: IssueSearchIssuesQuery,
1823    ) -> Result<(IssueListHeaders, Vec<Issue>), ForgejoError> {
1824        let request = self.get(&format!("repos/issues/search?{query}")).build()?;
1825        let response = self.execute(request).await?;
1826        match response.status().as_u16() {
1827            200 => Ok((response.headers().try_into()?, response.json().await?)),
1828            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1829        }
1830    }
1831
1832    /// Migrate a remote git repository
1833    ///
1834    /// - `body`: See [`MigrateRepoOptions`]
1835    pub async fn repo_migrate(&self, body: MigrateRepoOptions) -> Result<Repository, ForgejoError> {
1836        let request = self.post("repos/migrate").json(&body).build()?;
1837        let response = self.execute(request).await?;
1838        match response.status().as_u16() {
1839            201 => Ok(response.json().await?),
1840            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1841        }
1842    }
1843
1844    /// Search for repositories
1845    ///
1846    pub async fn repo_search(&self, query: RepoSearchQuery) -> Result<SearchResults, ForgejoError> {
1847        let request = self.get(&format!("repos/search?{query}")).build()?;
1848        let response = self.execute(request).await?;
1849        match response.status().as_u16() {
1850            200 => Ok(response.json().await?),
1851            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1852        }
1853    }
1854
1855    /// Get a repository
1856    ///
1857    /// - `owner`: owner of the repo
1858    /// - `repo`: name of the repo
1859    pub async fn repo_get(&self, owner: &str, repo: &str) -> Result<Repository, ForgejoError> {
1860        let request = self.get(&format!("repos/{owner}/{repo}")).build()?;
1861        let response = self.execute(request).await?;
1862        match response.status().as_u16() {
1863            200 => Ok(response.json().await?),
1864            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1865        }
1866    }
1867
1868    /// Delete a repository
1869    ///
1870    /// - `owner`: owner of the repo to delete
1871    /// - `repo`: name of the repo to delete
1872    pub async fn repo_delete(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
1873        let request = self.delete(&format!("repos/{owner}/{repo}")).build()?;
1874        let response = self.execute(request).await?;
1875        match response.status().as_u16() {
1876            204 => Ok(()),
1877            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1878        }
1879    }
1880
1881    /// Edit a repository's properties. Only fields that are set will be changed.
1882    ///
1883    /// - `owner`: owner of the repo to edit
1884    /// - `repo`: name of the repo to edit
1885    /// - `body`: Properties of a repo that you can edit
1886
1887    ///   See [`EditRepoOption`]
1888    pub async fn repo_edit(
1889        &self,
1890        owner: &str,
1891        repo: &str,
1892        body: EditRepoOption,
1893    ) -> Result<Repository, ForgejoError> {
1894        let request = self
1895            .patch(&format!("repos/{owner}/{repo}"))
1896            .json(&body)
1897            .build()?;
1898        let response = self.execute(request).await?;
1899        match response.status().as_u16() {
1900            200 => Ok(response.json().await?),
1901            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1902        }
1903    }
1904
1905    /// Get a repository's actions runner registration token
1906    ///
1907    /// - `owner`: owner of the repo
1908    /// - `repo`: name of the repo
1909    pub async fn repo_get_runner_registration_token(
1910        &self,
1911        owner: &str,
1912        repo: &str,
1913    ) -> Result<RegistrationTokenHeaders, ForgejoError> {
1914        let request = self
1915            .get(&format!(
1916                "repos/{owner}/{repo}/actions/runners/registration-token"
1917            ))
1918            .build()?;
1919        let response = self.execute(request).await?;
1920        match response.status().as_u16() {
1921            200 => Ok(response.headers().try_into()?),
1922            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1923        }
1924    }
1925
1926    /// List an repo's actions secrets
1927    ///
1928    /// - `owner`: owner of the repository
1929    /// - `repo`: name of the repository
1930    pub async fn repo_list_actions_secrets(
1931        &self,
1932        owner: &str,
1933        repo: &str,
1934        query: RepoListActionsSecretsQuery,
1935    ) -> Result<(SecretListHeaders, Vec<Secret>), ForgejoError> {
1936        let request = self
1937            .get(&format!("repos/{owner}/{repo}/actions/secrets?{query}"))
1938            .build()?;
1939        let response = self.execute(request).await?;
1940        match response.status().as_u16() {
1941            200 => Ok((response.headers().try_into()?, response.json().await?)),
1942            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1943        }
1944    }
1945
1946    /// Create or Update a secret value in a repository
1947    ///
1948    /// - `owner`: owner of the repository
1949    /// - `repo`: name of the repository
1950    /// - `secretname`: name of the secret
1951    /// - `body`: See [`CreateOrUpdateSecretOption`]
1952    pub async fn update_repo_secret(
1953        &self,
1954        owner: &str,
1955        repo: &str,
1956        secretname: &str,
1957        body: CreateOrUpdateSecretOption,
1958    ) -> Result<(), ForgejoError> {
1959        let request = self
1960            .put(&format!(
1961                "repos/{owner}/{repo}/actions/secrets/{secretname}"
1962            ))
1963            .json(&body)
1964            .build()?;
1965        let response = self.execute(request).await?;
1966        match response.status().as_u16() {
1967            201 => Ok(()),
1968            204 => Ok(()),
1969            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1970        }
1971    }
1972
1973    /// Delete a secret in a repository
1974    ///
1975    /// - `owner`: owner of the repository
1976    /// - `repo`: name of the repository
1977    /// - `secretname`: name of the secret
1978    pub async fn delete_repo_secret(
1979        &self,
1980        owner: &str,
1981        repo: &str,
1982        secretname: &str,
1983    ) -> Result<(), ForgejoError> {
1984        let request = self
1985            .delete(&format!(
1986                "repos/{owner}/{repo}/actions/secrets/{secretname}"
1987            ))
1988            .build()?;
1989        let response = self.execute(request).await?;
1990        match response.status().as_u16() {
1991            204 => Ok(()),
1992            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
1993        }
1994    }
1995
1996    /// List a repository's action tasks
1997    ///
1998    /// - `owner`: owner of the repo
1999    /// - `repo`: name of the repo
2000    pub async fn list_action_tasks(
2001        &self,
2002        owner: &str,
2003        repo: &str,
2004        query: ListActionTasksQuery,
2005    ) -> Result<ActionTaskResponse, ForgejoError> {
2006        let request = self
2007            .get(&format!("repos/{owner}/{repo}/actions/tasks?{query}"))
2008            .build()?;
2009        let response = self.execute(request).await?;
2010        match response.status().as_u16() {
2011            200 => Ok(response.json().await?),
2012            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2013        }
2014    }
2015
2016    /// Get repo-level variables list
2017    ///
2018    /// - `owner`: name of the owner
2019    /// - `repo`: name of the repository
2020    pub async fn get_repo_variables_list(
2021        &self,
2022        owner: &str,
2023        repo: &str,
2024        query: GetRepoVariablesListQuery,
2025    ) -> Result<(VariableListHeaders, Vec<ActionVariable>), ForgejoError> {
2026        let request = self
2027            .get(&format!("repos/{owner}/{repo}/actions/variables?{query}"))
2028            .build()?;
2029        let response = self.execute(request).await?;
2030        match response.status().as_u16() {
2031            200 => Ok((response.headers().try_into()?, response.json().await?)),
2032            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2033        }
2034    }
2035
2036    /// Get a repo-level variable
2037    ///
2038    /// - `owner`: name of the owner
2039    /// - `repo`: name of the repository
2040    /// - `variablename`: name of the variable
2041    pub async fn get_repo_variable(
2042        &self,
2043        owner: &str,
2044        repo: &str,
2045        variablename: &str,
2046    ) -> Result<ActionVariable, ForgejoError> {
2047        let request = self
2048            .get(&format!(
2049                "repos/{owner}/{repo}/actions/variables/{variablename}"
2050            ))
2051            .build()?;
2052        let response = self.execute(request).await?;
2053        match response.status().as_u16() {
2054            200 => Ok(response.json().await?),
2055            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2056        }
2057    }
2058
2059    /// Update a repo-level variable
2060    ///
2061    /// - `owner`: name of the owner
2062    /// - `repo`: name of the repository
2063    /// - `variablename`: name of the variable
2064    /// - `body`: See [`UpdateVariableOption`]
2065    pub async fn update_repo_variable(
2066        &self,
2067        owner: &str,
2068        repo: &str,
2069        variablename: &str,
2070        body: UpdateVariableOption,
2071    ) -> Result<(), ForgejoError> {
2072        let request = self
2073            .put(&format!(
2074                "repos/{owner}/{repo}/actions/variables/{variablename}"
2075            ))
2076            .json(&body)
2077            .build()?;
2078        let response = self.execute(request).await?;
2079        match response.status().as_u16() {
2080            201 => Ok(()),
2081            204 => Ok(()),
2082            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2083        }
2084    }
2085
2086    /// Create a repo-level variable
2087    ///
2088    /// - `owner`: name of the owner
2089    /// - `repo`: name of the repository
2090    /// - `variablename`: name of the variable
2091    /// - `body`: See [`CreateVariableOption`]
2092    pub async fn create_repo_variable(
2093        &self,
2094        owner: &str,
2095        repo: &str,
2096        variablename: &str,
2097        body: CreateVariableOption,
2098    ) -> Result<(), ForgejoError> {
2099        let request = self
2100            .post(&format!(
2101                "repos/{owner}/{repo}/actions/variables/{variablename}"
2102            ))
2103            .json(&body)
2104            .build()?;
2105        let response = self.execute(request).await?;
2106        match response.status().as_u16() {
2107            201 => Ok(()),
2108            204 => Ok(()),
2109            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2110        }
2111    }
2112
2113    /// Delete a repo-level variable
2114    ///
2115    /// - `owner`: name of the owner
2116    /// - `repo`: name of the repository
2117    /// - `variablename`: name of the variable
2118    pub async fn delete_repo_variable(
2119        &self,
2120        owner: &str,
2121        repo: &str,
2122        variablename: &str,
2123    ) -> Result<Option<ActionVariable>, ForgejoError> {
2124        let request = self
2125            .delete(&format!(
2126                "repos/{owner}/{repo}/actions/variables/{variablename}"
2127            ))
2128            .build()?;
2129        let response = self.execute(request).await?;
2130        match response.status().as_u16() {
2131            200 => Ok(Some(response.json().await?)),
2132            201 => Ok(None),
2133            204 => Ok(None),
2134            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2135        }
2136    }
2137
2138    /// Dispatches a workflow
2139    ///
2140    /// - `owner`: owner of the repo
2141    /// - `repo`: name of the repo
2142    /// - `workflowname`: name of the workflow
2143    /// - `body`: See [`DispatchWorkflowOption`]
2144    pub async fn dispatch_workflow(
2145        &self,
2146        owner: &str,
2147        repo: &str,
2148        workflowname: &str,
2149        body: DispatchWorkflowOption,
2150    ) -> Result<(), ForgejoError> {
2151        let request = self
2152            .post(&format!(
2153                "repos/{owner}/{repo}/actions/workflows/{workflowname}/dispatches"
2154            ))
2155            .json(&body)
2156            .build()?;
2157        let response = self.execute(request).await?;
2158        match response.status().as_u16() {
2159            204 => Ok(()),
2160            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2161        }
2162    }
2163
2164    /// List a repository's activity feeds
2165    ///
2166    /// - `owner`: owner of the repo
2167    /// - `repo`: name of the repo
2168    pub async fn repo_list_activity_feeds(
2169        &self,
2170        owner: &str,
2171        repo: &str,
2172        query: RepoListActivityFeedsQuery,
2173    ) -> Result<(ActivityFeedsListHeaders, Vec<Activity>), ForgejoError> {
2174        let request = self
2175            .get(&format!("repos/{owner}/{repo}/activities/feeds?{query}"))
2176            .build()?;
2177        let response = self.execute(request).await?;
2178        match response.status().as_u16() {
2179            200 => Ok((response.headers().try_into()?, response.json().await?)),
2180            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2181        }
2182    }
2183
2184    /// Get an archive of a repository
2185    ///
2186    /// - `owner`: owner of the repo
2187    /// - `repo`: name of the repo
2188    /// - `archive`: the git reference for download with attached archive format (e.g. master.zip)
2189    pub async fn repo_get_archive(
2190        &self,
2191        owner: &str,
2192        repo: &str,
2193        archive: &str,
2194    ) -> Result<Vec<u8>, ForgejoError> {
2195        let request = self
2196            .get(&format!("repos/{owner}/{repo}/archive/{archive}"))
2197            .build()?;
2198        let response = self.execute(request).await?;
2199        match response.status().as_u16() {
2200            200 => Ok(response.bytes().await?[..].to_vec()),
2201            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2202        }
2203    }
2204
2205    /// Return all users that have write access and can be assigned to issues
2206    ///
2207    /// - `owner`: owner of the repo
2208    /// - `repo`: name of the repo
2209    pub async fn repo_get_assignees(
2210        &self,
2211        owner: &str,
2212        repo: &str,
2213    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
2214        let request = self
2215            .get(&format!("repos/{owner}/{repo}/assignees"))
2216            .build()?;
2217        let response = self.execute(request).await?;
2218        match response.status().as_u16() {
2219            200 => Ok((response.headers().try_into()?, response.json().await?)),
2220            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2221        }
2222    }
2223
2224    /// Update avatar
2225    ///
2226    /// - `owner`: owner of the repo
2227    /// - `repo`: name of the repo
2228    /// - `body`: See [`UpdateRepoAvatarOption`]
2229    pub async fn repo_update_avatar(
2230        &self,
2231        owner: &str,
2232        repo: &str,
2233        body: UpdateRepoAvatarOption,
2234    ) -> Result<(), ForgejoError> {
2235        let request = self
2236            .post(&format!("repos/{owner}/{repo}/avatar"))
2237            .json(&body)
2238            .build()?;
2239        let response = self.execute(request).await?;
2240        match response.status().as_u16() {
2241            204 => Ok(()),
2242            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2243        }
2244    }
2245
2246    /// Delete avatar
2247    ///
2248    /// - `owner`: owner of the repo
2249    /// - `repo`: name of the repo
2250    pub async fn repo_delete_avatar(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
2251        let request = self
2252            .delete(&format!("repos/{owner}/{repo}/avatar"))
2253            .build()?;
2254        let response = self.execute(request).await?;
2255        match response.status().as_u16() {
2256            204 => Ok(()),
2257            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2258        }
2259    }
2260
2261    /// List branch protections for a repository
2262    ///
2263    /// - `owner`: owner of the repo
2264    /// - `repo`: name of the repo
2265    pub async fn repo_list_branch_protection(
2266        &self,
2267        owner: &str,
2268        repo: &str,
2269    ) -> Result<Vec<BranchProtection>, ForgejoError> {
2270        let request = self
2271            .get(&format!("repos/{owner}/{repo}/branch_protections"))
2272            .build()?;
2273        let response = self.execute(request).await?;
2274        match response.status().as_u16() {
2275            200 => Ok(response.json().await?),
2276            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2277        }
2278    }
2279
2280    /// Create a branch protections for a repository
2281    ///
2282    /// - `owner`: owner of the repo
2283    /// - `repo`: name of the repo
2284    /// - `body`: See [`CreateBranchProtectionOption`]
2285    pub async fn repo_create_branch_protection(
2286        &self,
2287        owner: &str,
2288        repo: &str,
2289        body: CreateBranchProtectionOption,
2290    ) -> Result<BranchProtection, ForgejoError> {
2291        let request = self
2292            .post(&format!("repos/{owner}/{repo}/branch_protections"))
2293            .json(&body)
2294            .build()?;
2295        let response = self.execute(request).await?;
2296        match response.status().as_u16() {
2297            201 => Ok(response.json().await?),
2298            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2299        }
2300    }
2301
2302    /// Get a specific branch protection for the repository
2303    ///
2304    /// - `owner`: owner of the repo
2305    /// - `repo`: name of the repo
2306    /// - `name`: name of protected branch
2307    pub async fn repo_get_branch_protection(
2308        &self,
2309        owner: &str,
2310        repo: &str,
2311        name: &str,
2312    ) -> Result<BranchProtection, ForgejoError> {
2313        let request = self
2314            .get(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
2315            .build()?;
2316        let response = self.execute(request).await?;
2317        match response.status().as_u16() {
2318            200 => Ok(response.json().await?),
2319            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2320        }
2321    }
2322
2323    /// Delete a specific branch protection for the repository
2324    ///
2325    /// - `owner`: owner of the repo
2326    /// - `repo`: name of the repo
2327    /// - `name`: name of protected branch
2328    pub async fn repo_delete_branch_protection(
2329        &self,
2330        owner: &str,
2331        repo: &str,
2332        name: &str,
2333    ) -> Result<(), ForgejoError> {
2334        let request = self
2335            .delete(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
2336            .build()?;
2337        let response = self.execute(request).await?;
2338        match response.status().as_u16() {
2339            204 => Ok(()),
2340            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2341        }
2342    }
2343
2344    /// Edit a branch protections for a repository. Only fields that are set will be changed
2345    ///
2346    /// - `owner`: owner of the repo
2347    /// - `repo`: name of the repo
2348    /// - `name`: name of protected branch
2349    /// - `body`: See [`EditBranchProtectionOption`]
2350    pub async fn repo_edit_branch_protection(
2351        &self,
2352        owner: &str,
2353        repo: &str,
2354        name: &str,
2355        body: EditBranchProtectionOption,
2356    ) -> Result<BranchProtection, ForgejoError> {
2357        let request = self
2358            .patch(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
2359            .json(&body)
2360            .build()?;
2361        let response = self.execute(request).await?;
2362        match response.status().as_u16() {
2363            200 => Ok(response.json().await?),
2364            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2365        }
2366    }
2367
2368    /// List a repository's branches
2369    ///
2370    /// - `owner`: owner of the repo
2371    /// - `repo`: name of the repo
2372    pub async fn repo_list_branches(
2373        &self,
2374        owner: &str,
2375        repo: &str,
2376        query: RepoListBranchesQuery,
2377    ) -> Result<(BranchListHeaders, Vec<Branch>), ForgejoError> {
2378        let request = self
2379            .get(&format!("repos/{owner}/{repo}/branches?{query}"))
2380            .build()?;
2381        let response = self.execute(request).await?;
2382        match response.status().as_u16() {
2383            200 => Ok((response.headers().try_into()?, response.json().await?)),
2384            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2385        }
2386    }
2387
2388    /// Create a branch
2389    ///
2390    /// - `owner`: owner of the repo
2391    /// - `repo`: name of the repo
2392    /// - `body`: See [`CreateBranchRepoOption`]
2393    pub async fn repo_create_branch(
2394        &self,
2395        owner: &str,
2396        repo: &str,
2397        body: CreateBranchRepoOption,
2398    ) -> Result<Branch, ForgejoError> {
2399        let request = self
2400            .post(&format!("repos/{owner}/{repo}/branches"))
2401            .json(&body)
2402            .build()?;
2403        let response = self.execute(request).await?;
2404        match response.status().as_u16() {
2405            201 => Ok(response.json().await?),
2406            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2407        }
2408    }
2409
2410    /// Retrieve a specific branch from a repository, including its effective branch protection
2411    ///
2412    /// - `owner`: owner of the repo
2413    /// - `repo`: name of the repo
2414    /// - `branch`: branch to get
2415    pub async fn repo_get_branch(
2416        &self,
2417        owner: &str,
2418        repo: &str,
2419        branch: &str,
2420    ) -> Result<Branch, ForgejoError> {
2421        let request = self
2422            .get(&format!("repos/{owner}/{repo}/branches/{branch}"))
2423            .build()?;
2424        let response = self.execute(request).await?;
2425        match response.status().as_u16() {
2426            200 => Ok(response.json().await?),
2427            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2428        }
2429    }
2430
2431    /// Delete a specific branch from a repository
2432    ///
2433    /// - `owner`: owner of the repo
2434    /// - `repo`: name of the repo
2435    /// - `branch`: branch to delete
2436    pub async fn repo_delete_branch(
2437        &self,
2438        owner: &str,
2439        repo: &str,
2440        branch: &str,
2441    ) -> Result<(), ForgejoError> {
2442        let request = self
2443            .delete(&format!("repos/{owner}/{repo}/branches/{branch}"))
2444            .build()?;
2445        let response = self.execute(request).await?;
2446        match response.status().as_u16() {
2447            204 => Ok(()),
2448            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2449        }
2450    }
2451
2452    /// Update a branch
2453    ///
2454    /// - `owner`: owner of the repo
2455    /// - `repo`: name of the repo
2456    /// - `branch`: name of the branch
2457    /// - `body`: See [`UpdateBranchRepoOption`]
2458    pub async fn repo_update_branch(
2459        &self,
2460        owner: &str,
2461        repo: &str,
2462        branch: &str,
2463        body: UpdateBranchRepoOption,
2464    ) -> Result<(), ForgejoError> {
2465        let request = self
2466            .patch(&format!("repos/{owner}/{repo}/branches/{branch}"))
2467            .json(&body)
2468            .build()?;
2469        let response = self.execute(request).await?;
2470        match response.status().as_u16() {
2471            204 => Ok(()),
2472            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2473        }
2474    }
2475
2476    /// List a repository's collaborators
2477    ///
2478    /// - `owner`: owner of the repo
2479    /// - `repo`: name of the repo
2480    pub async fn repo_list_collaborators(
2481        &self,
2482        owner: &str,
2483        repo: &str,
2484        query: RepoListCollaboratorsQuery,
2485    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
2486        let request = self
2487            .get(&format!("repos/{owner}/{repo}/collaborators?{query}"))
2488            .build()?;
2489        let response = self.execute(request).await?;
2490        match response.status().as_u16() {
2491            200 => Ok((response.headers().try_into()?, response.json().await?)),
2492            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2493        }
2494    }
2495
2496    /// Check if a user is a collaborator of a repository
2497    ///
2498    /// - `owner`: owner of the repo
2499    /// - `repo`: name of the repo
2500    /// - `collaborator`: username of the collaborator
2501    pub async fn repo_check_collaborator(
2502        &self,
2503        owner: &str,
2504        repo: &str,
2505        collaborator: &str,
2506    ) -> Result<(), ForgejoError> {
2507        let request = self
2508            .get(&format!(
2509                "repos/{owner}/{repo}/collaborators/{collaborator}"
2510            ))
2511            .build()?;
2512        let response = self.execute(request).await?;
2513        match response.status().as_u16() {
2514            204 => Ok(()),
2515            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2516        }
2517    }
2518
2519    /// Add a collaborator to a repository
2520    ///
2521    /// - `owner`: owner of the repo
2522    /// - `repo`: name of the repo
2523    /// - `collaborator`: username of the collaborator to add
2524    /// - `body`: See [`AddCollaboratorOption`]
2525    pub async fn repo_add_collaborator(
2526        &self,
2527        owner: &str,
2528        repo: &str,
2529        collaborator: &str,
2530        body: AddCollaboratorOption,
2531    ) -> Result<(), ForgejoError> {
2532        let request = self
2533            .put(&format!(
2534                "repos/{owner}/{repo}/collaborators/{collaborator}"
2535            ))
2536            .json(&body)
2537            .build()?;
2538        let response = self.execute(request).await?;
2539        match response.status().as_u16() {
2540            204 => Ok(()),
2541            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2542        }
2543    }
2544
2545    /// Delete a collaborator from a repository
2546    ///
2547    /// - `owner`: owner of the repo
2548    /// - `repo`: name of the repo
2549    /// - `collaborator`: username of the collaborator to delete
2550    pub async fn repo_delete_collaborator(
2551        &self,
2552        owner: &str,
2553        repo: &str,
2554        collaborator: &str,
2555    ) -> Result<(), ForgejoError> {
2556        let request = self
2557            .delete(&format!(
2558                "repos/{owner}/{repo}/collaborators/{collaborator}"
2559            ))
2560            .build()?;
2561        let response = self.execute(request).await?;
2562        match response.status().as_u16() {
2563            204 => Ok(()),
2564            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2565        }
2566    }
2567
2568    /// Get repository permissions for a user
2569    ///
2570    /// - `owner`: owner of the repo
2571    /// - `repo`: name of the repo
2572    /// - `collaborator`: username of the collaborator
2573    pub async fn repo_get_repo_permissions(
2574        &self,
2575        owner: &str,
2576        repo: &str,
2577        collaborator: &str,
2578    ) -> Result<RepoCollaboratorPermission, ForgejoError> {
2579        let request = self
2580            .get(&format!(
2581                "repos/{owner}/{repo}/collaborators/{collaborator}/permission"
2582            ))
2583            .build()?;
2584        let response = self.execute(request).await?;
2585        match response.status().as_u16() {
2586            200 => Ok(response.json().await?),
2587            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2588        }
2589    }
2590
2591    /// Get a list of all commits from a repository
2592    ///
2593    /// - `owner`: owner of the repo
2594    /// - `repo`: name of the repo
2595    pub async fn repo_get_all_commits(
2596        &self,
2597        owner: &str,
2598        repo: &str,
2599        query: RepoGetAllCommitsQuery,
2600    ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> {
2601        let request = self
2602            .get(&format!("repos/{owner}/{repo}/commits?{query}"))
2603            .build()?;
2604        let response = self.execute(request).await?;
2605        match response.status().as_u16() {
2606            200 => Ok((response.headers().try_into()?, response.json().await?)),
2607            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2608        }
2609    }
2610
2611    /// Get a commit's combined status, by branch/tag/commit reference
2612    ///
2613    /// - `owner`: owner of the repo
2614    /// - `repo`: name of the repo
2615    /// - `ref`: name of branch/tag/commit
2616    pub async fn repo_get_combined_status_by_ref(
2617        &self,
2618        owner: &str,
2619        repo: &str,
2620        r#ref: &str,
2621        query: RepoGetCombinedStatusByRefQuery,
2622    ) -> Result<CombinedStatus, ForgejoError> {
2623        let request = self
2624            .get(&format!(
2625                "repos/{owner}/{repo}/commits/{ref}/status?{query}"
2626            ))
2627            .build()?;
2628        let response = self.execute(request).await?;
2629        match response.status().as_u16() {
2630            200 => Ok(response.json().await?),
2631            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2632        }
2633    }
2634
2635    /// Get a commit's statuses, by branch/tag/commit reference
2636    ///
2637    /// - `owner`: owner of the repo
2638    /// - `repo`: name of the repo
2639    /// - `ref`: name of branch/tag/commit
2640    pub async fn repo_list_statuses_by_ref(
2641        &self,
2642        owner: &str,
2643        repo: &str,
2644        r#ref: &str,
2645        query: RepoListStatusesByRefQuery,
2646    ) -> Result<(CommitStatusListHeaders, Vec<CommitStatus>), ForgejoError> {
2647        let request = self
2648            .get(&format!(
2649                "repos/{owner}/{repo}/commits/{ref}/statuses?{query}"
2650            ))
2651            .build()?;
2652        let response = self.execute(request).await?;
2653        match response.status().as_u16() {
2654            200 => Ok((response.headers().try_into()?, response.json().await?)),
2655            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2656        }
2657    }
2658
2659    /// Get the pull request of the commit
2660    ///
2661    /// - `owner`: owner of the repo
2662    /// - `repo`: name of the repo
2663    /// - `sha`: SHA of the commit to get
2664    pub async fn repo_get_commit_pull_request(
2665        &self,
2666        owner: &str,
2667        repo: &str,
2668        sha: &str,
2669    ) -> Result<PullRequest, ForgejoError> {
2670        let request = self
2671            .get(&format!("repos/{owner}/{repo}/commits/{sha}/pull"))
2672            .build()?;
2673        let response = self.execute(request).await?;
2674        match response.status().as_u16() {
2675            200 => Ok(response.json().await?),
2676            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2677        }
2678    }
2679
2680    /// Get commit comparison information
2681    ///
2682    /// - `owner`: owner of the repo
2683    /// - `repo`: name of the repo
2684    /// - `basehead`: compare two branches or commits
2685    pub async fn repo_compare_diff(
2686        &self,
2687        owner: &str,
2688        repo: &str,
2689        basehead: &str,
2690    ) -> Result<Compare, ForgejoError> {
2691        let request = self
2692            .get(&format!("repos/{owner}/{repo}/compare/{basehead}"))
2693            .build()?;
2694        let response = self.execute(request).await?;
2695        match response.status().as_u16() {
2696            200 => Ok(response.json().await?),
2697            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2698        }
2699    }
2700
2701    /// Gets the metadata of all the entries of the root dir
2702    ///
2703    /// - `owner`: owner of the repo
2704    /// - `repo`: name of the repo
2705    pub async fn repo_get_contents_list(
2706        &self,
2707        owner: &str,
2708        repo: &str,
2709        query: RepoGetContentsListQuery,
2710    ) -> Result<Vec<ContentsResponse>, ForgejoError> {
2711        let request = self
2712            .get(&format!("repos/{owner}/{repo}/contents?{query}"))
2713            .build()?;
2714        let response = self.execute(request).await?;
2715        match response.status().as_u16() {
2716            200 => Ok(response.json().await?),
2717            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2718        }
2719    }
2720
2721    /// Modify multiple files in a repository
2722    ///
2723    /// - `owner`: owner of the repo
2724    /// - `repo`: name of the repo
2725    /// - `body`: See [`ChangeFilesOptions`]
2726    pub async fn repo_change_files(
2727        &self,
2728        owner: &str,
2729        repo: &str,
2730        body: ChangeFilesOptions,
2731    ) -> Result<FilesResponse, ForgejoError> {
2732        let request = self
2733            .post(&format!("repos/{owner}/{repo}/contents"))
2734            .json(&body)
2735            .build()?;
2736        let response = self.execute(request).await?;
2737        match response.status().as_u16() {
2738            201 => Ok(response.json().await?),
2739            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2740        }
2741    }
2742
2743    /// Gets the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir
2744    ///
2745    /// - `owner`: owner of the repo
2746    /// - `repo`: name of the repo
2747    /// - `filepath`: path of the dir, file, symlink or submodule in the repo
2748    pub async fn repo_get_contents(
2749        &self,
2750        owner: &str,
2751        repo: &str,
2752        filepath: &str,
2753        query: RepoGetContentsQuery,
2754    ) -> Result<ContentsResponse, ForgejoError> {
2755        let request = self
2756            .get(&format!("repos/{owner}/{repo}/contents/{filepath}?{query}"))
2757            .build()?;
2758        let response = self.execute(request).await?;
2759        match response.status().as_u16() {
2760            200 => Ok(response.json().await?),
2761            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2762        }
2763    }
2764
2765    /// Update a file in a repository
2766    ///
2767    /// - `owner`: owner of the repo
2768    /// - `repo`: name of the repo
2769    /// - `filepath`: path of the file to update
2770    /// - `body`: See [`UpdateFileOptions`]
2771    pub async fn repo_update_file(
2772        &self,
2773        owner: &str,
2774        repo: &str,
2775        filepath: &str,
2776        body: UpdateFileOptions,
2777    ) -> Result<FileResponse, ForgejoError> {
2778        let request = self
2779            .put(&format!("repos/{owner}/{repo}/contents/{filepath}"))
2780            .json(&body)
2781            .build()?;
2782        let response = self.execute(request).await?;
2783        match response.status().as_u16() {
2784            200 => Ok(response.json().await?),
2785            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2786        }
2787    }
2788
2789    /// Create a file in a repository
2790    ///
2791    /// - `owner`: owner of the repo
2792    /// - `repo`: name of the repo
2793    /// - `filepath`: path of the file to create
2794    /// - `body`: See [`CreateFileOptions`]
2795    pub async fn repo_create_file(
2796        &self,
2797        owner: &str,
2798        repo: &str,
2799        filepath: &str,
2800        body: CreateFileOptions,
2801    ) -> Result<FileResponse, ForgejoError> {
2802        let request = self
2803            .post(&format!("repos/{owner}/{repo}/contents/{filepath}"))
2804            .json(&body)
2805            .build()?;
2806        let response = self.execute(request).await?;
2807        match response.status().as_u16() {
2808            201 => Ok(response.json().await?),
2809            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2810        }
2811    }
2812
2813    /// Delete a file in a repository
2814    ///
2815    /// - `owner`: owner of the repo
2816    /// - `repo`: name of the repo
2817    /// - `filepath`: path of the file to delete
2818    /// - `body`: See [`DeleteFileOptions`]
2819    pub async fn repo_delete_file(
2820        &self,
2821        owner: &str,
2822        repo: &str,
2823        filepath: &str,
2824        body: DeleteFileOptions,
2825    ) -> Result<FileDeleteResponse, ForgejoError> {
2826        let request = self
2827            .delete(&format!("repos/{owner}/{repo}/contents/{filepath}"))
2828            .json(&body)
2829            .build()?;
2830        let response = self.execute(request).await?;
2831        match response.status().as_u16() {
2832            200 => Ok(response.json().await?),
2833            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2834        }
2835    }
2836
2837    /// Apply diff patch to repository
2838    ///
2839    /// - `owner`: owner of the repo
2840    /// - `repo`: name of the repo
2841    /// - `body`: See [`UpdateFileOptions`]
2842    pub async fn repo_apply_diff_patch(
2843        &self,
2844        owner: &str,
2845        repo: &str,
2846        body: UpdateFileOptions,
2847    ) -> Result<FileResponse, ForgejoError> {
2848        let request = self
2849            .post(&format!("repos/{owner}/{repo}/diffpatch"))
2850            .json(&body)
2851            .build()?;
2852        let response = self.execute(request).await?;
2853        match response.status().as_u16() {
2854            200 => Ok(response.json().await?),
2855            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2856        }
2857    }
2858
2859    /// Get the EditorConfig definitions of a file in a repository
2860    ///
2861    /// - `owner`: owner of the repo
2862    /// - `repo`: name of the repo
2863    /// - `filepath`: filepath of file to get
2864    pub async fn repo_get_editor_config(
2865        &self,
2866        owner: &str,
2867        repo: &str,
2868        filepath: &str,
2869        query: RepoGetEditorConfigQuery,
2870    ) -> Result<(), ForgejoError> {
2871        let request = self
2872            .get(&format!(
2873                "repos/{owner}/{repo}/editorconfig/{filepath}?{query}"
2874            ))
2875            .build()?;
2876        let response = self.execute(request).await?;
2877        match response.status().as_u16() {
2878            200 => Ok(()),
2879            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2880        }
2881    }
2882
2883    /// List a repository's flags
2884    ///
2885    /// - `owner`: owner of the repo
2886    /// - `repo`: name of the repo
2887    pub async fn repo_list_flags(
2888        &self,
2889        owner: &str,
2890        repo: &str,
2891    ) -> Result<Vec<String>, ForgejoError> {
2892        let request = self.get(&format!("repos/{owner}/{repo}/flags")).build()?;
2893        let response = self.execute(request).await?;
2894        match response.status().as_u16() {
2895            200 => Ok(response.json().await?),
2896            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2897        }
2898    }
2899
2900    /// Replace all flags of a repository
2901    ///
2902    /// - `owner`: owner of the repo
2903    /// - `repo`: name of the repo
2904    /// - `body`: See [`ReplaceFlagsOption`]
2905    pub async fn repo_replace_all_flags(
2906        &self,
2907        owner: &str,
2908        repo: &str,
2909        body: ReplaceFlagsOption,
2910    ) -> Result<(), ForgejoError> {
2911        let request = self
2912            .put(&format!("repos/{owner}/{repo}/flags"))
2913            .json(&body)
2914            .build()?;
2915        let response = self.execute(request).await?;
2916        match response.status().as_u16() {
2917            204 => Ok(()),
2918            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2919        }
2920    }
2921
2922    /// Remove all flags from a repository
2923    ///
2924    /// - `owner`: owner of the repo
2925    /// - `repo`: name of the repo
2926    pub async fn repo_delete_all_flags(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
2927        let request = self
2928            .delete(&format!("repos/{owner}/{repo}/flags"))
2929            .build()?;
2930        let response = self.execute(request).await?;
2931        match response.status().as_u16() {
2932            204 => Ok(()),
2933            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2934        }
2935    }
2936
2937    /// Check if a repository has a given flag
2938    ///
2939    /// - `owner`: owner of the repo
2940    /// - `repo`: name of the repo
2941    /// - `flag`: name of the flag
2942    pub async fn repo_check_flag(
2943        &self,
2944        owner: &str,
2945        repo: &str,
2946        flag: &str,
2947    ) -> Result<(), ForgejoError> {
2948        let request = self
2949            .get(&format!("repos/{owner}/{repo}/flags/{flag}"))
2950            .build()?;
2951        let response = self.execute(request).await?;
2952        match response.status().as_u16() {
2953            204 => Ok(()),
2954            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2955        }
2956    }
2957
2958    /// Add a flag to a repository
2959    ///
2960    /// - `owner`: owner of the repo
2961    /// - `repo`: name of the repo
2962    /// - `flag`: name of the flag
2963    pub async fn repo_add_flag(
2964        &self,
2965        owner: &str,
2966        repo: &str,
2967        flag: &str,
2968    ) -> Result<(), ForgejoError> {
2969        let request = self
2970            .put(&format!("repos/{owner}/{repo}/flags/{flag}"))
2971            .build()?;
2972        let response = self.execute(request).await?;
2973        match response.status().as_u16() {
2974            204 => Ok(()),
2975            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2976        }
2977    }
2978
2979    /// Remove a flag from a repository
2980    ///
2981    /// - `owner`: owner of the repo
2982    /// - `repo`: name of the repo
2983    /// - `flag`: name of the flag
2984    pub async fn repo_delete_flag(
2985        &self,
2986        owner: &str,
2987        repo: &str,
2988        flag: &str,
2989    ) -> Result<(), ForgejoError> {
2990        let request = self
2991            .delete(&format!("repos/{owner}/{repo}/flags/{flag}"))
2992            .build()?;
2993        let response = self.execute(request).await?;
2994        match response.status().as_u16() {
2995            204 => Ok(()),
2996            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
2997        }
2998    }
2999
3000    /// List a repository's forks
3001    ///
3002    /// - `owner`: owner of the repo
3003    /// - `repo`: name of the repo
3004    pub async fn list_forks(
3005        &self,
3006        owner: &str,
3007        repo: &str,
3008        query: ListForksQuery,
3009    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
3010        let request = self
3011            .get(&format!("repos/{owner}/{repo}/forks?{query}"))
3012            .build()?;
3013        let response = self.execute(request).await?;
3014        match response.status().as_u16() {
3015            200 => Ok((response.headers().try_into()?, response.json().await?)),
3016            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3017        }
3018    }
3019
3020    /// Fork a repository
3021    ///
3022    /// - `owner`: owner of the repo to fork
3023    /// - `repo`: name of the repo to fork
3024    /// - `body`: See [`CreateForkOption`]
3025    pub async fn create_fork(
3026        &self,
3027        owner: &str,
3028        repo: &str,
3029        body: CreateForkOption,
3030    ) -> Result<Repository, ForgejoError> {
3031        let request = self
3032            .post(&format!("repos/{owner}/{repo}/forks"))
3033            .json(&body)
3034            .build()?;
3035        let response = self.execute(request).await?;
3036        match response.status().as_u16() {
3037            202 => Ok(response.json().await?),
3038            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3039        }
3040    }
3041
3042    /// Gets the blob of a repository.
3043    ///
3044    /// - `owner`: owner of the repo
3045    /// - `repo`: name of the repo
3046    /// - `sha`: sha of the commit
3047    pub async fn get_blob(
3048        &self,
3049        owner: &str,
3050        repo: &str,
3051        sha: &str,
3052    ) -> Result<GitBlobResponse, ForgejoError> {
3053        let request = self
3054            .get(&format!("repos/{owner}/{repo}/git/blobs/{sha}"))
3055            .build()?;
3056        let response = self.execute(request).await?;
3057        match response.status().as_u16() {
3058            200 => Ok(response.json().await?),
3059            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3060        }
3061    }
3062
3063    /// Get a single commit from a repository
3064    ///
3065    /// - `owner`: owner of the repo
3066    /// - `repo`: name of the repo
3067    /// - `sha`: a git ref or commit sha
3068    pub async fn repo_get_single_commit(
3069        &self,
3070        owner: &str,
3071        repo: &str,
3072        sha: &str,
3073        query: RepoGetSingleCommitQuery,
3074    ) -> Result<Commit, ForgejoError> {
3075        let request = self
3076            .get(&format!("repos/{owner}/{repo}/git/commits/{sha}?{query}"))
3077            .build()?;
3078        let response = self.execute(request).await?;
3079        match response.status().as_u16() {
3080            200 => Ok(response.json().await?),
3081            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3082        }
3083    }
3084
3085    /// Get a commit's diff or patch
3086    ///
3087    /// - `owner`: owner of the repo
3088    /// - `repo`: name of the repo
3089    /// - `sha`: SHA of the commit to get
3090    /// - `diffType`: whether the output is diff or patch
3091    pub async fn repo_download_commit_diff_or_patch(
3092        &self,
3093        owner: &str,
3094        repo: &str,
3095        sha: &str,
3096        diff_type: &str,
3097    ) -> Result<String, ForgejoError> {
3098        let request = self
3099            .get(&format!(
3100                "repos/{owner}/{repo}/git/commits/{sha}.{diff_type}"
3101            ))
3102            .build()?;
3103        let response = self.execute(request).await?;
3104        match response.status().as_u16() {
3105            200 => Ok(response.text().await?),
3106            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3107        }
3108    }
3109
3110    /// Get a note corresponding to a single commit from a repository
3111    ///
3112    /// - `owner`: owner of the repo
3113    /// - `repo`: name of the repo
3114    /// - `sha`: a git ref or commit sha
3115    pub async fn repo_get_note(
3116        &self,
3117        owner: &str,
3118        repo: &str,
3119        sha: &str,
3120        query: RepoGetNoteQuery,
3121    ) -> Result<Note, ForgejoError> {
3122        let request = self
3123            .get(&format!("repos/{owner}/{repo}/git/notes/{sha}?{query}"))
3124            .build()?;
3125        let response = self.execute(request).await?;
3126        match response.status().as_u16() {
3127            200 => Ok(response.json().await?),
3128            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3129        }
3130    }
3131
3132    /// Set a note corresponding to a single commit from a repository
3133    ///
3134    /// - `owner`: owner of the repo
3135    /// - `repo`: name of the repo
3136    /// - `sha`: a git ref or commit sha
3137    /// - `body`: See [`NoteOptions`]
3138    pub async fn repo_set_note(
3139        &self,
3140        owner: &str,
3141        repo: &str,
3142        sha: &str,
3143        body: NoteOptions,
3144    ) -> Result<Note, ForgejoError> {
3145        let request = self
3146            .post(&format!("repos/{owner}/{repo}/git/notes/{sha}"))
3147            .json(&body)
3148            .build()?;
3149        let response = self.execute(request).await?;
3150        match response.status().as_u16() {
3151            200 => Ok(response.json().await?),
3152            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3153        }
3154    }
3155
3156    /// Removes a note corresponding to a single commit from a repository
3157    ///
3158    /// - `owner`: owner of the repo
3159    /// - `repo`: name of the repo
3160    /// - `sha`: a git ref or commit sha
3161    pub async fn repo_remove_note(
3162        &self,
3163        owner: &str,
3164        repo: &str,
3165        sha: &str,
3166    ) -> Result<(), ForgejoError> {
3167        let request = self
3168            .delete(&format!("repos/{owner}/{repo}/git/notes/{sha}"))
3169            .build()?;
3170        let response = self.execute(request).await?;
3171        match response.status().as_u16() {
3172            204 => Ok(()),
3173            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3174        }
3175    }
3176
3177    /// Get specified ref or filtered repository's refs
3178    ///
3179    /// - `owner`: owner of the repo
3180    /// - `repo`: name of the repo
3181    pub async fn repo_list_all_git_refs(
3182        &self,
3183        owner: &str,
3184        repo: &str,
3185    ) -> Result<Vec<Reference>, ForgejoError> {
3186        let request = self
3187            .get(&format!("repos/{owner}/{repo}/git/refs"))
3188            .build()?;
3189        let response = self.execute(request).await?;
3190        match response.status().as_u16() {
3191            200 => Ok(response.json().await?),
3192            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3193        }
3194    }
3195
3196    /// Get specified ref or filtered repository's refs
3197    ///
3198    /// - `owner`: owner of the repo
3199    /// - `repo`: name of the repo
3200    /// - `ref`: part or full name of the ref
3201    pub async fn repo_list_git_refs(
3202        &self,
3203        owner: &str,
3204        repo: &str,
3205        r#ref: &str,
3206    ) -> Result<Vec<Reference>, ForgejoError> {
3207        let request = self
3208            .get(&format!("repos/{owner}/{repo}/git/refs/{ref}"))
3209            .build()?;
3210        let response = self.execute(request).await?;
3211        match response.status().as_u16() {
3212            200 => Ok(response.json().await?),
3213            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3214        }
3215    }
3216
3217    /// Gets the tag object of an annotated tag (not lightweight tags)
3218    ///
3219    /// - `owner`: owner of the repo
3220    /// - `repo`: name of the repo
3221    /// - `sha`: sha of the tag. The Git tags API only supports annotated tag objects, not lightweight tags.
3222    pub async fn get_annotated_tag(
3223        &self,
3224        owner: &str,
3225        repo: &str,
3226        sha: &str,
3227    ) -> Result<AnnotatedTag, ForgejoError> {
3228        let request = self
3229            .get(&format!("repos/{owner}/{repo}/git/tags/{sha}"))
3230            .build()?;
3231        let response = self.execute(request).await?;
3232        match response.status().as_u16() {
3233            200 => Ok(response.json().await?),
3234            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3235        }
3236    }
3237
3238    /// Gets the tree of a repository.
3239    ///
3240    /// - `owner`: owner of the repo
3241    /// - `repo`: name of the repo
3242    /// - `sha`: sha of the commit
3243    pub async fn get_tree(
3244        &self,
3245        owner: &str,
3246        repo: &str,
3247        sha: &str,
3248        query: GetTreeQuery,
3249    ) -> Result<GitTreeResponse, ForgejoError> {
3250        let request = self
3251            .get(&format!("repos/{owner}/{repo}/git/trees/{sha}?{query}"))
3252            .build()?;
3253        let response = self.execute(request).await?;
3254        match response.status().as_u16() {
3255            200 => Ok(response.json().await?),
3256            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3257        }
3258    }
3259
3260    /// List the hooks in a repository
3261    ///
3262    /// - `owner`: owner of the repo
3263    /// - `repo`: name of the repo
3264    pub async fn repo_list_hooks(
3265        &self,
3266        owner: &str,
3267        repo: &str,
3268        query: RepoListHooksQuery,
3269    ) -> Result<(HookListHeaders, Vec<Hook>), ForgejoError> {
3270        let request = self
3271            .get(&format!("repos/{owner}/{repo}/hooks?{query}"))
3272            .build()?;
3273        let response = self.execute(request).await?;
3274        match response.status().as_u16() {
3275            200 => Ok((response.headers().try_into()?, response.json().await?)),
3276            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3277        }
3278    }
3279
3280    /// Create a hook
3281    ///
3282    /// - `owner`: owner of the repo
3283    /// - `repo`: name of the repo
3284    /// - `body`: See [`CreateHookOption`]
3285    pub async fn repo_create_hook(
3286        &self,
3287        owner: &str,
3288        repo: &str,
3289        body: CreateHookOption,
3290    ) -> Result<Hook, ForgejoError> {
3291        let request = self
3292            .post(&format!("repos/{owner}/{repo}/hooks"))
3293            .json(&body)
3294            .build()?;
3295        let response = self.execute(request).await?;
3296        match response.status().as_u16() {
3297            201 => Ok(response.json().await?),
3298            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3299        }
3300    }
3301
3302    /// List the Git hooks in a repository
3303    ///
3304    /// - `owner`: owner of the repo
3305    /// - `repo`: name of the repo
3306    pub async fn repo_list_git_hooks(
3307        &self,
3308        owner: &str,
3309        repo: &str,
3310    ) -> Result<(GitHookListHeaders, Vec<GitHook>), ForgejoError> {
3311        let request = self
3312            .get(&format!("repos/{owner}/{repo}/hooks/git"))
3313            .build()?;
3314        let response = self.execute(request).await?;
3315        match response.status().as_u16() {
3316            200 => Ok((response.headers().try_into()?, response.json().await?)),
3317            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3318        }
3319    }
3320
3321    /// Get a Git hook
3322    ///
3323    /// - `owner`: owner of the repo
3324    /// - `repo`: name of the repo
3325    /// - `id`: id of the hook to get
3326    pub async fn repo_get_git_hook(
3327        &self,
3328        owner: &str,
3329        repo: &str,
3330        id: &str,
3331    ) -> Result<GitHook, ForgejoError> {
3332        let request = self
3333            .get(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
3334            .build()?;
3335        let response = self.execute(request).await?;
3336        match response.status().as_u16() {
3337            200 => Ok(response.json().await?),
3338            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3339        }
3340    }
3341
3342    /// Delete a Git hook in a repository
3343    ///
3344    /// - `owner`: owner of the repo
3345    /// - `repo`: name of the repo
3346    /// - `id`: id of the hook to get
3347    pub async fn repo_delete_git_hook(
3348        &self,
3349        owner: &str,
3350        repo: &str,
3351        id: &str,
3352    ) -> Result<(), ForgejoError> {
3353        let request = self
3354            .delete(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
3355            .build()?;
3356        let response = self.execute(request).await?;
3357        match response.status().as_u16() {
3358            204 => Ok(()),
3359            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3360        }
3361    }
3362
3363    /// Edit a Git hook in a repository
3364    ///
3365    /// - `owner`: owner of the repo
3366    /// - `repo`: name of the repo
3367    /// - `id`: id of the hook to get
3368    /// - `body`: See [`EditGitHookOption`]
3369    pub async fn repo_edit_git_hook(
3370        &self,
3371        owner: &str,
3372        repo: &str,
3373        id: &str,
3374        body: EditGitHookOption,
3375    ) -> Result<GitHook, ForgejoError> {
3376        let request = self
3377            .patch(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
3378            .json(&body)
3379            .build()?;
3380        let response = self.execute(request).await?;
3381        match response.status().as_u16() {
3382            200 => Ok(response.json().await?),
3383            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3384        }
3385    }
3386
3387    /// Get a hook
3388    ///
3389    /// - `owner`: owner of the repo
3390    /// - `repo`: name of the repo
3391    /// - `id`: id of the hook to get
3392    pub async fn repo_get_hook(
3393        &self,
3394        owner: &str,
3395        repo: &str,
3396        id: u64,
3397    ) -> Result<Hook, ForgejoError> {
3398        let request = self
3399            .get(&format!("repos/{owner}/{repo}/hooks/{id}"))
3400            .build()?;
3401        let response = self.execute(request).await?;
3402        match response.status().as_u16() {
3403            200 => Ok(response.json().await?),
3404            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3405        }
3406    }
3407
3408    /// Delete a hook in a repository
3409    ///
3410    /// - `owner`: owner of the repo
3411    /// - `repo`: name of the repo
3412    /// - `id`: id of the hook to delete
3413    pub async fn repo_delete_hook(
3414        &self,
3415        owner: &str,
3416        repo: &str,
3417        id: u64,
3418    ) -> Result<(), ForgejoError> {
3419        let request = self
3420            .delete(&format!("repos/{owner}/{repo}/hooks/{id}"))
3421            .build()?;
3422        let response = self.execute(request).await?;
3423        match response.status().as_u16() {
3424            204 => Ok(()),
3425            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3426        }
3427    }
3428
3429    /// Edit a hook in a repository
3430    ///
3431    /// - `owner`: owner of the repo
3432    /// - `repo`: name of the repo
3433    /// - `id`: index of the hook
3434    /// - `body`: See [`EditHookOption`]
3435    pub async fn repo_edit_hook(
3436        &self,
3437        owner: &str,
3438        repo: &str,
3439        id: u64,
3440        body: EditHookOption,
3441    ) -> Result<Hook, ForgejoError> {
3442        let request = self
3443            .patch(&format!("repos/{owner}/{repo}/hooks/{id}"))
3444            .json(&body)
3445            .build()?;
3446        let response = self.execute(request).await?;
3447        match response.status().as_u16() {
3448            200 => Ok(response.json().await?),
3449            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3450        }
3451    }
3452
3453    /// Test a push webhook
3454    ///
3455    /// - `owner`: owner of the repo
3456    /// - `repo`: name of the repo
3457    /// - `id`: id of the hook to test
3458    pub async fn repo_test_hook(
3459        &self,
3460        owner: &str,
3461        repo: &str,
3462        id: u64,
3463        query: RepoTestHookQuery,
3464    ) -> Result<(), ForgejoError> {
3465        let request = self
3466            .post(&format!("repos/{owner}/{repo}/hooks/{id}/tests?{query}"))
3467            .build()?;
3468        let response = self.execute(request).await?;
3469        match response.status().as_u16() {
3470            204 => Ok(()),
3471            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3472        }
3473    }
3474
3475    /// Returns the issue config for a repo
3476    ///
3477    /// - `owner`: owner of the repo
3478    /// - `repo`: name of the repo
3479    pub async fn repo_get_issue_config(
3480        &self,
3481        owner: &str,
3482        repo: &str,
3483    ) -> Result<IssueConfig, ForgejoError> {
3484        let request = self
3485            .get(&format!("repos/{owner}/{repo}/issue_config"))
3486            .build()?;
3487        let response = self.execute(request).await?;
3488        match response.status().as_u16() {
3489            200 => Ok(response.json().await?),
3490            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3491        }
3492    }
3493
3494    /// Returns the validation information for a issue config
3495    ///
3496    /// - `owner`: owner of the repo
3497    /// - `repo`: name of the repo
3498    pub async fn repo_validate_issue_config(
3499        &self,
3500        owner: &str,
3501        repo: &str,
3502    ) -> Result<IssueConfigValidation, ForgejoError> {
3503        let request = self
3504            .get(&format!("repos/{owner}/{repo}/issue_config/validate"))
3505            .build()?;
3506        let response = self.execute(request).await?;
3507        match response.status().as_u16() {
3508            200 => Ok(response.json().await?),
3509            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3510        }
3511    }
3512
3513    /// Get available issue templates for a repository
3514    ///
3515    /// - `owner`: owner of the repo
3516    /// - `repo`: name of the repo
3517    pub async fn repo_get_issue_templates(
3518        &self,
3519        owner: &str,
3520        repo: &str,
3521    ) -> Result<Vec<IssueTemplate>, ForgejoError> {
3522        let request = self
3523            .get(&format!("repos/{owner}/{repo}/issue_templates"))
3524            .build()?;
3525        let response = self.execute(request).await?;
3526        match response.status().as_u16() {
3527            200 => Ok(response.json().await?),
3528            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3529        }
3530    }
3531
3532    /// List a repository's issues
3533    ///
3534    /// - `owner`: owner of the repo
3535    /// - `repo`: name of the repo
3536    pub async fn issue_list_issues(
3537        &self,
3538        owner: &str,
3539        repo: &str,
3540        query: IssueListIssuesQuery,
3541    ) -> Result<(IssueListHeaders, Vec<Issue>), ForgejoError> {
3542        let request = self
3543            .get(&format!("repos/{owner}/{repo}/issues?{query}"))
3544            .build()?;
3545        let response = self.execute(request).await?;
3546        match response.status().as_u16() {
3547            200 => Ok((response.headers().try_into()?, response.json().await?)),
3548            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3549        }
3550    }
3551
3552    /// Create an issue. If using deadline only the date will be taken into account, and time of day ignored.
3553    ///
3554    /// - `owner`: owner of the repo
3555    /// - `repo`: name of the repo
3556    /// - `body`: See [`CreateIssueOption`]
3557    pub async fn issue_create_issue(
3558        &self,
3559        owner: &str,
3560        repo: &str,
3561        body: CreateIssueOption,
3562    ) -> Result<Issue, ForgejoError> {
3563        let request = self
3564            .post(&format!("repos/{owner}/{repo}/issues"))
3565            .json(&body)
3566            .build()?;
3567        let response = self.execute(request).await?;
3568        match response.status().as_u16() {
3569            201 => Ok(response.json().await?),
3570            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3571        }
3572    }
3573
3574    /// List all comments in a repository
3575    ///
3576    /// - `owner`: owner of the repo
3577    /// - `repo`: name of the repo
3578    pub async fn issue_get_repo_comments(
3579        &self,
3580        owner: &str,
3581        repo: &str,
3582        query: IssueGetRepoCommentsQuery,
3583    ) -> Result<(CommentListHeaders, Vec<Comment>), ForgejoError> {
3584        let request = self
3585            .get(&format!("repos/{owner}/{repo}/issues/comments?{query}"))
3586            .build()?;
3587        let response = self.execute(request).await?;
3588        match response.status().as_u16() {
3589            200 => Ok((response.headers().try_into()?, response.json().await?)),
3590            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3591        }
3592    }
3593
3594    /// Get a comment
3595    ///
3596    /// - `owner`: owner of the repo
3597    /// - `repo`: name of the repo
3598    /// - `id`: id of the comment
3599    pub async fn issue_get_comment(
3600        &self,
3601        owner: &str,
3602        repo: &str,
3603        id: u64,
3604    ) -> Result<Option<Comment>, ForgejoError> {
3605        let request = self
3606            .get(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
3607            .build()?;
3608        let response = self.execute(request).await?;
3609        match response.status().as_u16() {
3610            200 => Ok(Some(response.json().await?)),
3611            204 => Ok(None),
3612            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3613        }
3614    }
3615
3616    /// Delete a comment
3617    ///
3618    /// - `owner`: owner of the repo
3619    /// - `repo`: name of the repo
3620    /// - `id`: id of comment to delete
3621    pub async fn issue_delete_comment(
3622        &self,
3623        owner: &str,
3624        repo: &str,
3625        id: u64,
3626    ) -> Result<(), ForgejoError> {
3627        let request = self
3628            .delete(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
3629            .build()?;
3630        let response = self.execute(request).await?;
3631        match response.status().as_u16() {
3632            204 => Ok(()),
3633            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3634        }
3635    }
3636
3637    /// Edit a comment
3638    ///
3639    /// - `owner`: owner of the repo
3640    /// - `repo`: name of the repo
3641    /// - `id`: id of the comment to edit
3642    /// - `body`: See [`EditIssueCommentOption`]
3643    pub async fn issue_edit_comment(
3644        &self,
3645        owner: &str,
3646        repo: &str,
3647        id: u64,
3648        body: EditIssueCommentOption,
3649    ) -> Result<Option<Comment>, ForgejoError> {
3650        let request = self
3651            .patch(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
3652            .json(&body)
3653            .build()?;
3654        let response = self.execute(request).await?;
3655        match response.status().as_u16() {
3656            200 => Ok(Some(response.json().await?)),
3657            204 => Ok(None),
3658            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3659        }
3660    }
3661
3662    /// List comment's attachments
3663    ///
3664    /// - `owner`: owner of the repo
3665    /// - `repo`: name of the repo
3666    /// - `id`: id of the comment
3667    pub async fn issue_list_issue_comment_attachments(
3668        &self,
3669        owner: &str,
3670        repo: &str,
3671        id: u64,
3672    ) -> Result<Vec<Attachment>, ForgejoError> {
3673        let request = self
3674            .get(&format!("repos/{owner}/{repo}/issues/comments/{id}/assets"))
3675            .build()?;
3676        let response = self.execute(request).await?;
3677        match response.status().as_u16() {
3678            200 => Ok(response.json().await?),
3679            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3680        }
3681    }
3682
3683    /// Create a comment attachment
3684    ///
3685    /// - `owner`: owner of the repo
3686    /// - `repo`: name of the repo
3687    /// - `id`: id of the comment
3688    /// - `attachment`: attachment to upload
3689    pub async fn issue_create_issue_comment_attachment(
3690        &self,
3691        owner: &str,
3692        repo: &str,
3693        id: u64,
3694        attachment: Vec<u8>,
3695        query: IssueCreateIssueCommentAttachmentQuery,
3696    ) -> Result<Attachment, ForgejoError> {
3697        let builder = self.post(&format!(
3698            "repos/{owner}/{repo}/issues/comments/{id}/assets?{query}"
3699        ));
3700        let builder = builder.multipart(
3701            reqwest::multipart::Form::new().part(
3702                "attachment",
3703                reqwest::multipart::Part::bytes(attachment)
3704                    .file_name("file")
3705                    .mime_str("*/*")
3706                    .unwrap(),
3707            ),
3708        );
3709        let request = builder.build()?;
3710        let response = self.execute(request).await?;
3711        match response.status().as_u16() {
3712            201 => Ok(response.json().await?),
3713            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3714        }
3715    }
3716
3717    /// Get a comment attachment
3718    ///
3719    /// - `owner`: owner of the repo
3720    /// - `repo`: name of the repo
3721    /// - `id`: id of the comment
3722    /// - `attachment_id`: id of the attachment to get
3723    pub async fn issue_get_issue_comment_attachment(
3724        &self,
3725        owner: &str,
3726        repo: &str,
3727        id: u64,
3728        attachment_id: u64,
3729    ) -> Result<Attachment, ForgejoError> {
3730        let request = self
3731            .get(&format!(
3732                "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
3733            ))
3734            .build()?;
3735        let response = self.execute(request).await?;
3736        match response.status().as_u16() {
3737            200 => Ok(response.json().await?),
3738            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3739        }
3740    }
3741
3742    /// Delete a comment attachment
3743    ///
3744    /// - `owner`: owner of the repo
3745    /// - `repo`: name of the repo
3746    /// - `id`: id of the comment
3747    /// - `attachment_id`: id of the attachment to delete
3748    pub async fn issue_delete_issue_comment_attachment(
3749        &self,
3750        owner: &str,
3751        repo: &str,
3752        id: u64,
3753        attachment_id: u64,
3754    ) -> Result<(), ForgejoError> {
3755        let request = self
3756            .delete(&format!(
3757                "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
3758            ))
3759            .build()?;
3760        let response = self.execute(request).await?;
3761        match response.status().as_u16() {
3762            204 => Ok(()),
3763            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3764        }
3765    }
3766
3767    /// Edit a comment attachment
3768    ///
3769    /// - `owner`: owner of the repo
3770    /// - `repo`: name of the repo
3771    /// - `id`: id of the comment
3772    /// - `attachment_id`: id of the attachment to edit
3773    /// - `body`: See [`EditAttachmentOptions`]
3774    pub async fn issue_edit_issue_comment_attachment(
3775        &self,
3776        owner: &str,
3777        repo: &str,
3778        id: u64,
3779        attachment_id: u64,
3780        body: EditAttachmentOptions,
3781    ) -> Result<Attachment, ForgejoError> {
3782        let request = self
3783            .patch(&format!(
3784                "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
3785            ))
3786            .json(&body)
3787            .build()?;
3788        let response = self.execute(request).await?;
3789        match response.status().as_u16() {
3790            201 => Ok(response.json().await?),
3791            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3792        }
3793    }
3794
3795    /// Get a list of reactions from a comment of an issue
3796    ///
3797    /// - `owner`: owner of the repo
3798    /// - `repo`: name of the repo
3799    /// - `id`: id of the comment to edit
3800    pub async fn issue_get_comment_reactions(
3801        &self,
3802        owner: &str,
3803        repo: &str,
3804        id: u64,
3805    ) -> Result<(ReactionListHeaders, Vec<Reaction>), ForgejoError> {
3806        let request = self
3807            .get(&format!(
3808                "repos/{owner}/{repo}/issues/comments/{id}/reactions"
3809            ))
3810            .build()?;
3811        let response = self.execute(request).await?;
3812        match response.status().as_u16() {
3813            200 => Ok((response.headers().try_into()?, response.json().await?)),
3814            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3815        }
3816    }
3817
3818    /// Add a reaction to a comment of an issue
3819    ///
3820    /// - `owner`: owner of the repo
3821    /// - `repo`: name of the repo
3822    /// - `id`: id of the comment to edit
3823    /// - `content`: See [`EditReactionOption`]
3824    pub async fn issue_post_comment_reaction(
3825        &self,
3826        owner: &str,
3827        repo: &str,
3828        id: u64,
3829        content: EditReactionOption,
3830    ) -> Result<Reaction, ForgejoError> {
3831        let request = self
3832            .post(&format!(
3833                "repos/{owner}/{repo}/issues/comments/{id}/reactions"
3834            ))
3835            .json(&content)
3836            .build()?;
3837        let response = self.execute(request).await?;
3838        match response.status().as_u16() {
3839            200 => Ok(response.json().await?),
3840            201 => Ok(response.json().await?),
3841            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3842        }
3843    }
3844
3845    /// Remove a reaction from a comment of an issue
3846    ///
3847    /// - `owner`: owner of the repo
3848    /// - `repo`: name of the repo
3849    /// - `id`: id of the comment to edit
3850    /// - `content`: See [`EditReactionOption`]
3851    pub async fn issue_delete_comment_reaction(
3852        &self,
3853        owner: &str,
3854        repo: &str,
3855        id: u64,
3856        content: EditReactionOption,
3857    ) -> Result<(), ForgejoError> {
3858        let request = self
3859            .delete(&format!(
3860                "repos/{owner}/{repo}/issues/comments/{id}/reactions"
3861            ))
3862            .json(&content)
3863            .build()?;
3864        let response = self.execute(request).await?;
3865        match response.status().as_u16() {
3866            200 => Ok(()),
3867            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3868        }
3869    }
3870
3871    /// List a repo's pinned issues
3872    ///
3873    /// - `owner`: owner of the repo
3874    /// - `repo`: name of the repo
3875    pub async fn repo_list_pinned_issues(
3876        &self,
3877        owner: &str,
3878        repo: &str,
3879    ) -> Result<(IssueListHeaders, Vec<Issue>), ForgejoError> {
3880        let request = self
3881            .get(&format!("repos/{owner}/{repo}/issues/pinned"))
3882            .build()?;
3883        let response = self.execute(request).await?;
3884        match response.status().as_u16() {
3885            200 => Ok((response.headers().try_into()?, response.json().await?)),
3886            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3887        }
3888    }
3889
3890    /// Get an issue
3891    ///
3892    /// - `owner`: owner of the repo
3893    /// - `repo`: name of the repo
3894    /// - `index`: index of the issue to get
3895    pub async fn issue_get_issue(
3896        &self,
3897        owner: &str,
3898        repo: &str,
3899        index: u64,
3900    ) -> Result<Issue, ForgejoError> {
3901        let request = self
3902            .get(&format!("repos/{owner}/{repo}/issues/{index}"))
3903            .build()?;
3904        let response = self.execute(request).await?;
3905        match response.status().as_u16() {
3906            200 => Ok(response.json().await?),
3907            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3908        }
3909    }
3910
3911    /// Delete an issue
3912    ///
3913    /// - `owner`: owner of the repo
3914    /// - `repo`: name of the repo
3915    /// - `index`: index of issue to delete
3916    pub async fn issue_delete(
3917        &self,
3918        owner: &str,
3919        repo: &str,
3920        index: u64,
3921    ) -> Result<(), ForgejoError> {
3922        let request = self
3923            .delete(&format!("repos/{owner}/{repo}/issues/{index}"))
3924            .build()?;
3925        let response = self.execute(request).await?;
3926        match response.status().as_u16() {
3927            204 => Ok(()),
3928            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3929        }
3930    }
3931
3932    /// Edit an issue. If using deadline only the date will be taken into account, and time of day ignored.
3933    ///
3934    /// - `owner`: owner of the repo
3935    /// - `repo`: name of the repo
3936    /// - `index`: index of the issue to edit
3937    /// - `body`: See [`EditIssueOption`]
3938    pub async fn issue_edit_issue(
3939        &self,
3940        owner: &str,
3941        repo: &str,
3942        index: u64,
3943        body: EditIssueOption,
3944    ) -> Result<Issue, ForgejoError> {
3945        let request = self
3946            .patch(&format!("repos/{owner}/{repo}/issues/{index}"))
3947            .json(&body)
3948            .build()?;
3949        let response = self.execute(request).await?;
3950        match response.status().as_u16() {
3951            201 => Ok(response.json().await?),
3952            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3953        }
3954    }
3955
3956    /// List issue's attachments
3957    ///
3958    /// - `owner`: owner of the repo
3959    /// - `repo`: name of the repo
3960    /// - `index`: index of the issue
3961    pub async fn issue_list_issue_attachments(
3962        &self,
3963        owner: &str,
3964        repo: &str,
3965        index: u64,
3966    ) -> Result<Vec<Attachment>, ForgejoError> {
3967        let request = self
3968            .get(&format!("repos/{owner}/{repo}/issues/{index}/assets"))
3969            .build()?;
3970        let response = self.execute(request).await?;
3971        match response.status().as_u16() {
3972            200 => Ok(response.json().await?),
3973            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
3974        }
3975    }
3976
3977    /// Create an issue attachment
3978    ///
3979    /// - `owner`: owner of the repo
3980    /// - `repo`: name of the repo
3981    /// - `index`: index of the issue
3982    /// - `attachment`: attachment to upload
3983    pub async fn issue_create_issue_attachment(
3984        &self,
3985        owner: &str,
3986        repo: &str,
3987        index: u64,
3988        attachment: Vec<u8>,
3989        query: IssueCreateIssueAttachmentQuery,
3990    ) -> Result<Attachment, ForgejoError> {
3991        let builder = self.post(&format!(
3992            "repos/{owner}/{repo}/issues/{index}/assets?{query}"
3993        ));
3994        let builder = builder.multipart(
3995            reqwest::multipart::Form::new().part(
3996                "attachment",
3997                reqwest::multipart::Part::bytes(attachment)
3998                    .file_name("file")
3999                    .mime_str("*/*")
4000                    .unwrap(),
4001            ),
4002        );
4003        let request = builder.build()?;
4004        let response = self.execute(request).await?;
4005        match response.status().as_u16() {
4006            201 => Ok(response.json().await?),
4007            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4008        }
4009    }
4010
4011    /// Get an issue attachment
4012    ///
4013    /// - `owner`: owner of the repo
4014    /// - `repo`: name of the repo
4015    /// - `index`: index of the issue
4016    /// - `attachment_id`: id of the attachment to get
4017    pub async fn issue_get_issue_attachment(
4018        &self,
4019        owner: &str,
4020        repo: &str,
4021        index: u64,
4022        attachment_id: u64,
4023    ) -> Result<Attachment, ForgejoError> {
4024        let request = self
4025            .get(&format!(
4026                "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
4027            ))
4028            .build()?;
4029        let response = self.execute(request).await?;
4030        match response.status().as_u16() {
4031            200 => Ok(response.json().await?),
4032            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4033        }
4034    }
4035
4036    /// Delete an issue attachment
4037    ///
4038    /// - `owner`: owner of the repo
4039    /// - `repo`: name of the repo
4040    /// - `index`: index of the issue
4041    /// - `attachment_id`: id of the attachment to delete
4042    pub async fn issue_delete_issue_attachment(
4043        &self,
4044        owner: &str,
4045        repo: &str,
4046        index: u64,
4047        attachment_id: u64,
4048    ) -> Result<(), ForgejoError> {
4049        let request = self
4050            .delete(&format!(
4051                "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
4052            ))
4053            .build()?;
4054        let response = self.execute(request).await?;
4055        match response.status().as_u16() {
4056            204 => Ok(()),
4057            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4058        }
4059    }
4060
4061    /// Edit an issue attachment
4062    ///
4063    /// - `owner`: owner of the repo
4064    /// - `repo`: name of the repo
4065    /// - `index`: index of the issue
4066    /// - `attachment_id`: id of the attachment to edit
4067    /// - `body`: See [`EditAttachmentOptions`]
4068    pub async fn issue_edit_issue_attachment(
4069        &self,
4070        owner: &str,
4071        repo: &str,
4072        index: u64,
4073        attachment_id: u64,
4074        body: EditAttachmentOptions,
4075    ) -> Result<Attachment, ForgejoError> {
4076        let request = self
4077            .patch(&format!(
4078                "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
4079            ))
4080            .json(&body)
4081            .build()?;
4082        let response = self.execute(request).await?;
4083        match response.status().as_u16() {
4084            201 => Ok(response.json().await?),
4085            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4086        }
4087    }
4088
4089    /// List issues that are blocked by this issue
4090    ///
4091    /// - `owner`: owner of the repo
4092    /// - `repo`: name of the repo
4093    /// - `index`: index of the issue
4094    pub async fn issue_list_blocks(
4095        &self,
4096        owner: &str,
4097        repo: &str,
4098        index: &str,
4099        query: IssueListBlocksQuery,
4100    ) -> Result<(IssueListHeaders, Vec<Issue>), ForgejoError> {
4101        let request = self
4102            .get(&format!(
4103                "repos/{owner}/{repo}/issues/{index}/blocks?{query}"
4104            ))
4105            .build()?;
4106        let response = self.execute(request).await?;
4107        match response.status().as_u16() {
4108            200 => Ok((response.headers().try_into()?, response.json().await?)),
4109            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4110        }
4111    }
4112
4113    /// Block the issue given in the body by the issue in path
4114    ///
4115    /// - `owner`: owner of the repo
4116    /// - `repo`: name of the repo
4117    /// - `index`: index of the issue
4118    /// - `body`: See [`IssueMeta`]
4119    pub async fn issue_create_issue_blocking(
4120        &self,
4121        owner: &str,
4122        repo: &str,
4123        index: &str,
4124        body: IssueMeta,
4125    ) -> Result<Issue, ForgejoError> {
4126        let request = self
4127            .post(&format!("repos/{owner}/{repo}/issues/{index}/blocks"))
4128            .json(&body)
4129            .build()?;
4130        let response = self.execute(request).await?;
4131        match response.status().as_u16() {
4132            201 => Ok(response.json().await?),
4133            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4134        }
4135    }
4136
4137    /// Unblock the issue given in the body by the issue in path
4138    ///
4139    /// - `owner`: owner of the repo
4140    /// - `repo`: name of the repo
4141    /// - `index`: index of the issue
4142    /// - `body`: See [`IssueMeta`]
4143    pub async fn issue_remove_issue_blocking(
4144        &self,
4145        owner: &str,
4146        repo: &str,
4147        index: &str,
4148        body: IssueMeta,
4149    ) -> Result<Issue, ForgejoError> {
4150        let request = self
4151            .delete(&format!("repos/{owner}/{repo}/issues/{index}/blocks"))
4152            .json(&body)
4153            .build()?;
4154        let response = self.execute(request).await?;
4155        match response.status().as_u16() {
4156            200 => Ok(response.json().await?),
4157            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4158        }
4159    }
4160
4161    /// List all comments on an issue
4162    ///
4163    /// - `owner`: owner of the repo
4164    /// - `repo`: name of the repo
4165    /// - `index`: index of the issue
4166    pub async fn issue_get_comments(
4167        &self,
4168        owner: &str,
4169        repo: &str,
4170        index: u64,
4171        query: IssueGetCommentsQuery,
4172    ) -> Result<(CommentListHeaders, Vec<Comment>), ForgejoError> {
4173        let request = self
4174            .get(&format!(
4175                "repos/{owner}/{repo}/issues/{index}/comments?{query}"
4176            ))
4177            .build()?;
4178        let response = self.execute(request).await?;
4179        match response.status().as_u16() {
4180            200 => Ok((response.headers().try_into()?, response.json().await?)),
4181            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4182        }
4183    }
4184
4185    /// Add a comment to an issue
4186    ///
4187    /// - `owner`: owner of the repo
4188    /// - `repo`: name of the repo
4189    /// - `index`: index of the issue
4190    /// - `body`: See [`CreateIssueCommentOption`]
4191    pub async fn issue_create_comment(
4192        &self,
4193        owner: &str,
4194        repo: &str,
4195        index: u64,
4196        body: CreateIssueCommentOption,
4197    ) -> Result<Comment, ForgejoError> {
4198        let request = self
4199            .post(&format!("repos/{owner}/{repo}/issues/{index}/comments"))
4200            .json(&body)
4201            .build()?;
4202        let response = self.execute(request).await?;
4203        match response.status().as_u16() {
4204            201 => Ok(response.json().await?),
4205            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4206        }
4207    }
4208
4209    /// Delete a comment
4210    ///
4211    /// - `owner`: owner of the repo
4212    /// - `repo`: name of the repo
4213    /// - `index`: this parameter is ignored
4214    /// - `id`: id of comment to delete
4215    pub async fn issue_delete_comment_deprecated(
4216        &self,
4217        owner: &str,
4218        repo: &str,
4219        index: u32,
4220        id: u64,
4221    ) -> Result<(), ForgejoError> {
4222        let request = self
4223            .delete(&format!(
4224                "repos/{owner}/{repo}/issues/{index}/comments/{id}"
4225            ))
4226            .build()?;
4227        let response = self.execute(request).await?;
4228        match response.status().as_u16() {
4229            204 => Ok(()),
4230            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4231        }
4232    }
4233
4234    /// Edit a comment
4235    ///
4236    /// - `owner`: owner of the repo
4237    /// - `repo`: name of the repo
4238    /// - `index`: this parameter is ignored
4239    /// - `id`: id of the comment to edit
4240    /// - `body`: See [`EditIssueCommentOption`]
4241    pub async fn issue_edit_comment_deprecated(
4242        &self,
4243        owner: &str,
4244        repo: &str,
4245        index: u32,
4246        id: u64,
4247        body: EditIssueCommentOption,
4248    ) -> Result<Option<Comment>, ForgejoError> {
4249        let request = self
4250            .patch(&format!(
4251                "repos/{owner}/{repo}/issues/{index}/comments/{id}"
4252            ))
4253            .json(&body)
4254            .build()?;
4255        let response = self.execute(request).await?;
4256        match response.status().as_u16() {
4257            200 => Ok(Some(response.json().await?)),
4258            204 => Ok(None),
4259            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4260        }
4261    }
4262
4263    /// Set an issue deadline. If set to null, the deadline is deleted. If using deadline only the date will be taken into account, and time of day ignored.
4264    ///
4265    /// - `owner`: owner of the repo
4266    /// - `repo`: name of the repo
4267    /// - `index`: index of the issue to create or update a deadline on
4268    /// - `body`: See [`EditDeadlineOption`]
4269    pub async fn issue_edit_issue_deadline(
4270        &self,
4271        owner: &str,
4272        repo: &str,
4273        index: u64,
4274        body: EditDeadlineOption,
4275    ) -> Result<IssueDeadline, ForgejoError> {
4276        let request = self
4277            .post(&format!("repos/{owner}/{repo}/issues/{index}/deadline"))
4278            .json(&body)
4279            .build()?;
4280        let response = self.execute(request).await?;
4281        match response.status().as_u16() {
4282            201 => Ok(response.json().await?),
4283            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4284        }
4285    }
4286
4287    /// List an issue's dependencies, i.e all issues that block this issue.
4288    ///
4289    /// - `owner`: owner of the repo
4290    /// - `repo`: name of the repo
4291    /// - `index`: index of the issue
4292    pub async fn issue_list_issue_dependencies(
4293        &self,
4294        owner: &str,
4295        repo: &str,
4296        index: &str,
4297        query: IssueListIssueDependenciesQuery,
4298    ) -> Result<(IssueListHeaders, Vec<Issue>), ForgejoError> {
4299        let request = self
4300            .get(&format!(
4301                "repos/{owner}/{repo}/issues/{index}/dependencies?{query}"
4302            ))
4303            .build()?;
4304        let response = self.execute(request).await?;
4305        match response.status().as_u16() {
4306            200 => Ok((response.headers().try_into()?, response.json().await?)),
4307            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4308        }
4309    }
4310
4311    /// Make the issue in the url depend on the issue in the form.
4312    ///
4313    /// - `owner`: owner of the repo
4314    /// - `repo`: name of the repo
4315    /// - `index`: index of the issue
4316    /// - `body`: See [`IssueMeta`]
4317    pub async fn issue_create_issue_dependencies(
4318        &self,
4319        owner: &str,
4320        repo: &str,
4321        index: &str,
4322        body: IssueMeta,
4323    ) -> Result<Issue, ForgejoError> {
4324        let request = self
4325            .post(&format!("repos/{owner}/{repo}/issues/{index}/dependencies"))
4326            .json(&body)
4327            .build()?;
4328        let response = self.execute(request).await?;
4329        match response.status().as_u16() {
4330            201 => Ok(response.json().await?),
4331            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4332        }
4333    }
4334
4335    /// Remove an issue dependency
4336    ///
4337    /// - `owner`: owner of the repo
4338    /// - `repo`: name of the repo
4339    /// - `index`: index of the issue
4340    /// - `body`: See [`IssueMeta`]
4341    pub async fn issue_remove_issue_dependencies(
4342        &self,
4343        owner: &str,
4344        repo: &str,
4345        index: &str,
4346        body: IssueMeta,
4347    ) -> Result<Issue, ForgejoError> {
4348        let request = self
4349            .delete(&format!("repos/{owner}/{repo}/issues/{index}/dependencies"))
4350            .json(&body)
4351            .build()?;
4352        let response = self.execute(request).await?;
4353        match response.status().as_u16() {
4354            200 => Ok(response.json().await?),
4355            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4356        }
4357    }
4358
4359    /// Get an issue's labels
4360    ///
4361    /// - `owner`: owner of the repo
4362    /// - `repo`: name of the repo
4363    /// - `index`: index of the issue
4364    pub async fn issue_get_labels(
4365        &self,
4366        owner: &str,
4367        repo: &str,
4368        index: u64,
4369    ) -> Result<(LabelListHeaders, Vec<Label>), ForgejoError> {
4370        let request = self
4371            .get(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
4372            .build()?;
4373        let response = self.execute(request).await?;
4374        match response.status().as_u16() {
4375            200 => Ok((response.headers().try_into()?, response.json().await?)),
4376            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4377        }
4378    }
4379
4380    /// Replace an issue's labels
4381    ///
4382    /// - `owner`: owner of the repo
4383    /// - `repo`: name of the repo
4384    /// - `index`: index of the issue
4385    /// - `body`: See [`IssueLabelsOption`]
4386    pub async fn issue_replace_labels(
4387        &self,
4388        owner: &str,
4389        repo: &str,
4390        index: u64,
4391        body: IssueLabelsOption,
4392    ) -> Result<(LabelListHeaders, Vec<Label>), ForgejoError> {
4393        let request = self
4394            .put(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
4395            .json(&body)
4396            .build()?;
4397        let response = self.execute(request).await?;
4398        match response.status().as_u16() {
4399            200 => Ok((response.headers().try_into()?, response.json().await?)),
4400            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4401        }
4402    }
4403
4404    /// Add a label to an issue
4405    ///
4406    /// - `owner`: owner of the repo
4407    /// - `repo`: name of the repo
4408    /// - `index`: index of the issue
4409    /// - `body`: See [`IssueLabelsOption`]
4410    pub async fn issue_add_label(
4411        &self,
4412        owner: &str,
4413        repo: &str,
4414        index: u64,
4415        body: IssueLabelsOption,
4416    ) -> Result<(LabelListHeaders, Vec<Label>), ForgejoError> {
4417        let request = self
4418            .post(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
4419            .json(&body)
4420            .build()?;
4421        let response = self.execute(request).await?;
4422        match response.status().as_u16() {
4423            200 => Ok((response.headers().try_into()?, response.json().await?)),
4424            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4425        }
4426    }
4427
4428    /// Remove all labels from an issue
4429    ///
4430    /// - `owner`: owner of the repo
4431    /// - `repo`: name of the repo
4432    /// - `index`: index of the issue
4433    /// - `body`: See [`DeleteLabelsOption`]
4434    pub async fn issue_clear_labels(
4435        &self,
4436        owner: &str,
4437        repo: &str,
4438        index: u64,
4439        body: DeleteLabelsOption,
4440    ) -> Result<(), ForgejoError> {
4441        let request = self
4442            .delete(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
4443            .json(&body)
4444            .build()?;
4445        let response = self.execute(request).await?;
4446        match response.status().as_u16() {
4447            204 => Ok(()),
4448            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4449        }
4450    }
4451
4452    /// Remove a label from an issue
4453    ///
4454    /// - `owner`: owner of the repo
4455    /// - `repo`: name of the repo
4456    /// - `index`: index of the issue
4457    /// - `id`: id of the label to remove
4458    /// - `body`: See [`DeleteLabelsOption`]
4459    pub async fn issue_remove_label(
4460        &self,
4461        owner: &str,
4462        repo: &str,
4463        index: u64,
4464        id: u64,
4465        body: DeleteLabelsOption,
4466    ) -> Result<(), ForgejoError> {
4467        let request = self
4468            .delete(&format!("repos/{owner}/{repo}/issues/{index}/labels/{id}"))
4469            .json(&body)
4470            .build()?;
4471        let response = self.execute(request).await?;
4472        match response.status().as_u16() {
4473            204 => Ok(()),
4474            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4475        }
4476    }
4477
4478    /// Pin an Issue
4479    ///
4480    /// - `owner`: owner of the repo
4481    /// - `repo`: name of the repo
4482    /// - `index`: index of issue to pin
4483    pub async fn pin_issue(&self, owner: &str, repo: &str, index: u64) -> Result<(), ForgejoError> {
4484        let request = self
4485            .post(&format!("repos/{owner}/{repo}/issues/{index}/pin"))
4486            .build()?;
4487        let response = self.execute(request).await?;
4488        match response.status().as_u16() {
4489            204 => Ok(()),
4490            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4491        }
4492    }
4493
4494    /// Unpin an Issue
4495    ///
4496    /// - `owner`: owner of the repo
4497    /// - `repo`: name of the repo
4498    /// - `index`: index of issue to unpin
4499    pub async fn unpin_issue(
4500        &self,
4501        owner: &str,
4502        repo: &str,
4503        index: u64,
4504    ) -> Result<(), ForgejoError> {
4505        let request = self
4506            .delete(&format!("repos/{owner}/{repo}/issues/{index}/pin"))
4507            .build()?;
4508        let response = self.execute(request).await?;
4509        match response.status().as_u16() {
4510            204 => Ok(()),
4511            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4512        }
4513    }
4514
4515    /// Moves the Pin to the given Position
4516    ///
4517    /// - `owner`: owner of the repo
4518    /// - `repo`: name of the repo
4519    /// - `index`: index of issue
4520    /// - `position`: the new position
4521    pub async fn move_issue_pin(
4522        &self,
4523        owner: &str,
4524        repo: &str,
4525        index: u64,
4526        position: u64,
4527    ) -> Result<(), ForgejoError> {
4528        let request = self
4529            .patch(&format!(
4530                "repos/{owner}/{repo}/issues/{index}/pin/{position}"
4531            ))
4532            .build()?;
4533        let response = self.execute(request).await?;
4534        match response.status().as_u16() {
4535            204 => Ok(()),
4536            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4537        }
4538    }
4539
4540    /// Get a list reactions of an issue
4541    ///
4542    /// - `owner`: owner of the repo
4543    /// - `repo`: name of the repo
4544    /// - `index`: index of the issue
4545    pub async fn issue_get_issue_reactions(
4546        &self,
4547        owner: &str,
4548        repo: &str,
4549        index: u64,
4550        query: IssueGetIssueReactionsQuery,
4551    ) -> Result<(ReactionListHeaders, Vec<Reaction>), ForgejoError> {
4552        let request = self
4553            .get(&format!(
4554                "repos/{owner}/{repo}/issues/{index}/reactions?{query}"
4555            ))
4556            .build()?;
4557        let response = self.execute(request).await?;
4558        match response.status().as_u16() {
4559            200 => Ok((response.headers().try_into()?, response.json().await?)),
4560            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4561        }
4562    }
4563
4564    /// Add a reaction to an issue
4565    ///
4566    /// - `owner`: owner of the repo
4567    /// - `repo`: name of the repo
4568    /// - `index`: index of the issue
4569    /// - `content`: See [`EditReactionOption`]
4570    pub async fn issue_post_issue_reaction(
4571        &self,
4572        owner: &str,
4573        repo: &str,
4574        index: u64,
4575        content: EditReactionOption,
4576    ) -> Result<Reaction, ForgejoError> {
4577        let request = self
4578            .post(&format!("repos/{owner}/{repo}/issues/{index}/reactions"))
4579            .json(&content)
4580            .build()?;
4581        let response = self.execute(request).await?;
4582        match response.status().as_u16() {
4583            200 => Ok(response.json().await?),
4584            201 => Ok(response.json().await?),
4585            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4586        }
4587    }
4588
4589    /// Remove a reaction from an issue
4590    ///
4591    /// - `owner`: owner of the repo
4592    /// - `repo`: name of the repo
4593    /// - `index`: index of the issue
4594    /// - `content`: See [`EditReactionOption`]
4595    pub async fn issue_delete_issue_reaction(
4596        &self,
4597        owner: &str,
4598        repo: &str,
4599        index: u64,
4600        content: EditReactionOption,
4601    ) -> Result<(), ForgejoError> {
4602        let request = self
4603            .delete(&format!("repos/{owner}/{repo}/issues/{index}/reactions"))
4604            .json(&content)
4605            .build()?;
4606        let response = self.execute(request).await?;
4607        match response.status().as_u16() {
4608            200 => Ok(()),
4609            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4610        }
4611    }
4612
4613    /// Delete an issue's existing stopwatch.
4614    ///
4615    /// - `owner`: owner of the repo
4616    /// - `repo`: name of the repo
4617    /// - `index`: index of the issue to stop the stopwatch on
4618    pub async fn issue_delete_stop_watch(
4619        &self,
4620        owner: &str,
4621        repo: &str,
4622        index: u64,
4623    ) -> Result<(), ForgejoError> {
4624        let request = self
4625            .delete(&format!(
4626                "repos/{owner}/{repo}/issues/{index}/stopwatch/delete"
4627            ))
4628            .build()?;
4629        let response = self.execute(request).await?;
4630        match response.status().as_u16() {
4631            204 => Ok(()),
4632            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4633        }
4634    }
4635
4636    /// Start stopwatch on an issue.
4637    ///
4638    /// - `owner`: owner of the repo
4639    /// - `repo`: name of the repo
4640    /// - `index`: index of the issue to create the stopwatch on
4641    pub async fn issue_start_stop_watch(
4642        &self,
4643        owner: &str,
4644        repo: &str,
4645        index: u64,
4646    ) -> Result<(), ForgejoError> {
4647        let request = self
4648            .post(&format!(
4649                "repos/{owner}/{repo}/issues/{index}/stopwatch/start"
4650            ))
4651            .build()?;
4652        let response = self.execute(request).await?;
4653        match response.status().as_u16() {
4654            201 => Ok(()),
4655            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4656        }
4657    }
4658
4659    /// Stop an issue's existing stopwatch.
4660    ///
4661    /// - `owner`: owner of the repo
4662    /// - `repo`: name of the repo
4663    /// - `index`: index of the issue to stop the stopwatch on
4664    pub async fn issue_stop_stop_watch(
4665        &self,
4666        owner: &str,
4667        repo: &str,
4668        index: u64,
4669    ) -> Result<(), ForgejoError> {
4670        let request = self
4671            .post(&format!(
4672                "repos/{owner}/{repo}/issues/{index}/stopwatch/stop"
4673            ))
4674            .build()?;
4675        let response = self.execute(request).await?;
4676        match response.status().as_u16() {
4677            201 => Ok(()),
4678            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4679        }
4680    }
4681
4682    /// Get users who subscribed on an issue.
4683    ///
4684    /// - `owner`: owner of the repo
4685    /// - `repo`: name of the repo
4686    /// - `index`: index of the issue
4687    pub async fn issue_subscriptions(
4688        &self,
4689        owner: &str,
4690        repo: &str,
4691        index: u64,
4692        query: IssueSubscriptionsQuery,
4693    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
4694        let request = self
4695            .get(&format!(
4696                "repos/{owner}/{repo}/issues/{index}/subscriptions?{query}"
4697            ))
4698            .build()?;
4699        let response = self.execute(request).await?;
4700        match response.status().as_u16() {
4701            200 => Ok((response.headers().try_into()?, response.json().await?)),
4702            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4703        }
4704    }
4705
4706    /// Check if user is subscribed to an issue
4707    ///
4708    /// - `owner`: owner of the repo
4709    /// - `repo`: name of the repo
4710    /// - `index`: index of the issue
4711    pub async fn issue_check_subscription(
4712        &self,
4713        owner: &str,
4714        repo: &str,
4715        index: u64,
4716    ) -> Result<WatchInfo, ForgejoError> {
4717        let request = self
4718            .get(&format!(
4719                "repos/{owner}/{repo}/issues/{index}/subscriptions/check"
4720            ))
4721            .build()?;
4722        let response = self.execute(request).await?;
4723        match response.status().as_u16() {
4724            200 => Ok(response.json().await?),
4725            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4726        }
4727    }
4728
4729    /// Subscribe user to issue
4730    ///
4731    /// - `owner`: owner of the repo
4732    /// - `repo`: name of the repo
4733    /// - `index`: index of the issue
4734    /// - `user`: user to subscribe
4735    pub async fn issue_add_subscription(
4736        &self,
4737        owner: &str,
4738        repo: &str,
4739        index: u64,
4740        user: &str,
4741    ) -> Result<(), ForgejoError> {
4742        let request = self
4743            .put(&format!(
4744                "repos/{owner}/{repo}/issues/{index}/subscriptions/{user}"
4745            ))
4746            .build()?;
4747        let response = self.execute(request).await?;
4748        match response.status().as_u16() {
4749            200 => Ok(()),
4750            201 => Ok(()),
4751            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4752        }
4753    }
4754
4755    /// Unsubscribe user from issue
4756    ///
4757    /// - `owner`: owner of the repo
4758    /// - `repo`: name of the repo
4759    /// - `index`: index of the issue
4760    /// - `user`: user witch unsubscribe
4761    pub async fn issue_delete_subscription(
4762        &self,
4763        owner: &str,
4764        repo: &str,
4765        index: u64,
4766        user: &str,
4767    ) -> Result<(), ForgejoError> {
4768        let request = self
4769            .delete(&format!(
4770                "repos/{owner}/{repo}/issues/{index}/subscriptions/{user}"
4771            ))
4772            .build()?;
4773        let response = self.execute(request).await?;
4774        match response.status().as_u16() {
4775            200 => Ok(()),
4776            201 => Ok(()),
4777            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4778        }
4779    }
4780
4781    /// List all comments and events on an issue
4782    ///
4783    /// - `owner`: owner of the repo
4784    /// - `repo`: name of the repo
4785    /// - `index`: index of the issue
4786    pub async fn issue_get_comments_and_timeline(
4787        &self,
4788        owner: &str,
4789        repo: &str,
4790        index: u64,
4791        query: IssueGetCommentsAndTimelineQuery,
4792    ) -> Result<(TimelineListHeaders, Vec<TimelineComment>), ForgejoError> {
4793        let request = self
4794            .get(&format!(
4795                "repos/{owner}/{repo}/issues/{index}/timeline?{query}"
4796            ))
4797            .build()?;
4798        let response = self.execute(request).await?;
4799        match response.status().as_u16() {
4800            200 => Ok((response.headers().try_into()?, response.json().await?)),
4801            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4802        }
4803    }
4804
4805    /// List an issue's tracked times
4806    ///
4807    /// - `owner`: owner of the repo
4808    /// - `repo`: name of the repo
4809    /// - `index`: index of the issue
4810    pub async fn issue_tracked_times(
4811        &self,
4812        owner: &str,
4813        repo: &str,
4814        index: u64,
4815        query: IssueTrackedTimesQuery,
4816    ) -> Result<(TrackedTimeListHeaders, Vec<TrackedTime>), ForgejoError> {
4817        let request = self
4818            .get(&format!(
4819                "repos/{owner}/{repo}/issues/{index}/times?{query}"
4820            ))
4821            .build()?;
4822        let response = self.execute(request).await?;
4823        match response.status().as_u16() {
4824            200 => Ok((response.headers().try_into()?, response.json().await?)),
4825            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4826        }
4827    }
4828
4829    /// Add tracked time to a issue
4830    ///
4831    /// - `owner`: owner of the repo
4832    /// - `repo`: name of the repo
4833    /// - `index`: index of the issue
4834    /// - `body`: See [`AddTimeOption`]
4835    pub async fn issue_add_time(
4836        &self,
4837        owner: &str,
4838        repo: &str,
4839        index: u64,
4840        body: AddTimeOption,
4841    ) -> Result<TrackedTime, ForgejoError> {
4842        let request = self
4843            .post(&format!("repos/{owner}/{repo}/issues/{index}/times"))
4844            .json(&body)
4845            .build()?;
4846        let response = self.execute(request).await?;
4847        match response.status().as_u16() {
4848            200 => Ok(response.json().await?),
4849            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4850        }
4851    }
4852
4853    /// Reset a tracked time of an issue
4854    ///
4855    /// - `owner`: owner of the repo
4856    /// - `repo`: name of the repo
4857    /// - `index`: index of the issue to add tracked time to
4858    pub async fn issue_reset_time(
4859        &self,
4860        owner: &str,
4861        repo: &str,
4862        index: u64,
4863    ) -> Result<(), ForgejoError> {
4864        let request = self
4865            .delete(&format!("repos/{owner}/{repo}/issues/{index}/times"))
4866            .build()?;
4867        let response = self.execute(request).await?;
4868        match response.status().as_u16() {
4869            204 => Ok(()),
4870            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4871        }
4872    }
4873
4874    /// Delete specific tracked time
4875    ///
4876    /// - `owner`: owner of the repo
4877    /// - `repo`: name of the repo
4878    /// - `index`: index of the issue
4879    /// - `id`: id of time to delete
4880    pub async fn issue_delete_time(
4881        &self,
4882        owner: &str,
4883        repo: &str,
4884        index: u64,
4885        id: u64,
4886    ) -> Result<(), ForgejoError> {
4887        let request = self
4888            .delete(&format!("repos/{owner}/{repo}/issues/{index}/times/{id}"))
4889            .build()?;
4890        let response = self.execute(request).await?;
4891        match response.status().as_u16() {
4892            204 => Ok(()),
4893            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4894        }
4895    }
4896
4897    /// List a repository's keys
4898    ///
4899    /// - `owner`: owner of the repo
4900    /// - `repo`: name of the repo
4901    pub async fn repo_list_keys(
4902        &self,
4903        owner: &str,
4904        repo: &str,
4905        query: RepoListKeysQuery,
4906    ) -> Result<(DeployKeyListHeaders, Vec<DeployKey>), ForgejoError> {
4907        let request = self
4908            .get(&format!("repos/{owner}/{repo}/keys?{query}"))
4909            .build()?;
4910        let response = self.execute(request).await?;
4911        match response.status().as_u16() {
4912            200 => Ok((response.headers().try_into()?, response.json().await?)),
4913            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4914        }
4915    }
4916
4917    /// Add a key to a repository
4918    ///
4919    /// - `owner`: owner of the repo
4920    /// - `repo`: name of the repo
4921    /// - `body`: See [`CreateKeyOption`]
4922    pub async fn repo_create_key(
4923        &self,
4924        owner: &str,
4925        repo: &str,
4926        body: CreateKeyOption,
4927    ) -> Result<DeployKey, ForgejoError> {
4928        let request = self
4929            .post(&format!("repos/{owner}/{repo}/keys"))
4930            .json(&body)
4931            .build()?;
4932        let response = self.execute(request).await?;
4933        match response.status().as_u16() {
4934            201 => Ok(response.json().await?),
4935            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4936        }
4937    }
4938
4939    /// Get a repository's key by id
4940    ///
4941    /// - `owner`: owner of the repo
4942    /// - `repo`: name of the repo
4943    /// - `id`: id of the key to get
4944    pub async fn repo_get_key(
4945        &self,
4946        owner: &str,
4947        repo: &str,
4948        id: u64,
4949    ) -> Result<DeployKey, ForgejoError> {
4950        let request = self
4951            .get(&format!("repos/{owner}/{repo}/keys/{id}"))
4952            .build()?;
4953        let response = self.execute(request).await?;
4954        match response.status().as_u16() {
4955            200 => Ok(response.json().await?),
4956            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4957        }
4958    }
4959
4960    /// Delete a key from a repository
4961    ///
4962    /// - `owner`: owner of the repo
4963    /// - `repo`: name of the repo
4964    /// - `id`: id of the key to delete
4965    pub async fn repo_delete_key(
4966        &self,
4967        owner: &str,
4968        repo: &str,
4969        id: u64,
4970    ) -> Result<(), ForgejoError> {
4971        let request = self
4972            .delete(&format!("repos/{owner}/{repo}/keys/{id}"))
4973            .build()?;
4974        let response = self.execute(request).await?;
4975        match response.status().as_u16() {
4976            204 => Ok(()),
4977            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4978        }
4979    }
4980
4981    /// Get all of a repository's labels
4982    ///
4983    /// - `owner`: owner of the repo
4984    /// - `repo`: name of the repo
4985    pub async fn issue_list_labels(
4986        &self,
4987        owner: &str,
4988        repo: &str,
4989        query: IssueListLabelsQuery,
4990    ) -> Result<(LabelListHeaders, Vec<Label>), ForgejoError> {
4991        let request = self
4992            .get(&format!("repos/{owner}/{repo}/labels?{query}"))
4993            .build()?;
4994        let response = self.execute(request).await?;
4995        match response.status().as_u16() {
4996            200 => Ok((response.headers().try_into()?, response.json().await?)),
4997            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
4998        }
4999    }
5000
5001    /// Create a label
5002    ///
5003    /// - `owner`: owner of the repo
5004    /// - `repo`: name of the repo
5005    /// - `body`: See [`CreateLabelOption`]
5006    pub async fn issue_create_label(
5007        &self,
5008        owner: &str,
5009        repo: &str,
5010        body: CreateLabelOption,
5011    ) -> Result<Label, ForgejoError> {
5012        let request = self
5013            .post(&format!("repos/{owner}/{repo}/labels"))
5014            .json(&body)
5015            .build()?;
5016        let response = self.execute(request).await?;
5017        match response.status().as_u16() {
5018            201 => Ok(response.json().await?),
5019            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5020        }
5021    }
5022
5023    /// Get a single label
5024    ///
5025    /// - `owner`: owner of the repo
5026    /// - `repo`: name of the repo
5027    /// - `id`: id of the label to get
5028    pub async fn issue_get_label(
5029        &self,
5030        owner: &str,
5031        repo: &str,
5032        id: u64,
5033    ) -> Result<Label, ForgejoError> {
5034        let request = self
5035            .get(&format!("repos/{owner}/{repo}/labels/{id}"))
5036            .build()?;
5037        let response = self.execute(request).await?;
5038        match response.status().as_u16() {
5039            200 => Ok(response.json().await?),
5040            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5041        }
5042    }
5043
5044    /// Delete a label
5045    ///
5046    /// - `owner`: owner of the repo
5047    /// - `repo`: name of the repo
5048    /// - `id`: id of the label to delete
5049    pub async fn issue_delete_label(
5050        &self,
5051        owner: &str,
5052        repo: &str,
5053        id: u64,
5054    ) -> Result<(), ForgejoError> {
5055        let request = self
5056            .delete(&format!("repos/{owner}/{repo}/labels/{id}"))
5057            .build()?;
5058        let response = self.execute(request).await?;
5059        match response.status().as_u16() {
5060            204 => Ok(()),
5061            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5062        }
5063    }
5064
5065    /// Update a label
5066    ///
5067    /// - `owner`: owner of the repo
5068    /// - `repo`: name of the repo
5069    /// - `id`: id of the label to edit
5070    /// - `body`: See [`EditLabelOption`]
5071    pub async fn issue_edit_label(
5072        &self,
5073        owner: &str,
5074        repo: &str,
5075        id: u64,
5076        body: EditLabelOption,
5077    ) -> Result<Label, ForgejoError> {
5078        let request = self
5079            .patch(&format!("repos/{owner}/{repo}/labels/{id}"))
5080            .json(&body)
5081            .build()?;
5082        let response = self.execute(request).await?;
5083        match response.status().as_u16() {
5084            200 => Ok(response.json().await?),
5085            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5086        }
5087    }
5088
5089    /// Get languages and number of bytes of code written
5090    ///
5091    /// - `owner`: owner of the repo
5092    /// - `repo`: name of the repo
5093    pub async fn repo_get_languages(
5094        &self,
5095        owner: &str,
5096        repo: &str,
5097    ) -> Result<BTreeMap<String, i64>, ForgejoError> {
5098        let request = self
5099            .get(&format!("repos/{owner}/{repo}/languages"))
5100            .build()?;
5101        let response = self.execute(request).await?;
5102        match response.status().as_u16() {
5103            200 => Ok(response.json().await?),
5104            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5105        }
5106    }
5107
5108    /// Get a file or it's LFS object from a repository
5109    ///
5110    /// - `owner`: owner of the repo
5111    /// - `repo`: name of the repo
5112    /// - `filepath`: filepath of the file to get
5113    pub async fn repo_get_raw_file_or_lfs(
5114        &self,
5115        owner: &str,
5116        repo: &str,
5117        filepath: &str,
5118        query: RepoGetRawFileOrLfsQuery,
5119    ) -> Result<Vec<u8>, ForgejoError> {
5120        let request = self
5121            .get(&format!("repos/{owner}/{repo}/media/{filepath}?{query}"))
5122            .build()?;
5123        let response = self.execute(request).await?;
5124        match response.status().as_u16() {
5125            200 => Ok(response.bytes().await?[..].to_vec()),
5126            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5127        }
5128    }
5129
5130    /// Get all of a repository's opened milestones
5131    ///
5132    /// - `owner`: owner of the repo
5133    /// - `repo`: name of the repo
5134    pub async fn issue_get_milestones_list(
5135        &self,
5136        owner: &str,
5137        repo: &str,
5138        query: IssueGetMilestonesListQuery,
5139    ) -> Result<(MilestoneListHeaders, Vec<Milestone>), ForgejoError> {
5140        let request = self
5141            .get(&format!("repos/{owner}/{repo}/milestones?{query}"))
5142            .build()?;
5143        let response = self.execute(request).await?;
5144        match response.status().as_u16() {
5145            200 => Ok((response.headers().try_into()?, response.json().await?)),
5146            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5147        }
5148    }
5149
5150    /// Create a milestone
5151    ///
5152    /// - `owner`: owner of the repo
5153    /// - `repo`: name of the repo
5154    /// - `body`: See [`CreateMilestoneOption`]
5155    pub async fn issue_create_milestone(
5156        &self,
5157        owner: &str,
5158        repo: &str,
5159        body: CreateMilestoneOption,
5160    ) -> Result<Milestone, ForgejoError> {
5161        let request = self
5162            .post(&format!("repos/{owner}/{repo}/milestones"))
5163            .json(&body)
5164            .build()?;
5165        let response = self.execute(request).await?;
5166        match response.status().as_u16() {
5167            201 => Ok(response.json().await?),
5168            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5169        }
5170    }
5171
5172    /// Get a milestone
5173    ///
5174    /// - `owner`: owner of the repo
5175    /// - `repo`: name of the repo
5176    /// - `id`: the milestone to get, identified by ID and if not available by name
5177    pub async fn issue_get_milestone(
5178        &self,
5179        owner: &str,
5180        repo: &str,
5181        id: &str,
5182    ) -> Result<Milestone, ForgejoError> {
5183        let request = self
5184            .get(&format!("repos/{owner}/{repo}/milestones/{id}"))
5185            .build()?;
5186        let response = self.execute(request).await?;
5187        match response.status().as_u16() {
5188            200 => Ok(response.json().await?),
5189            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5190        }
5191    }
5192
5193    /// Delete a milestone
5194    ///
5195    /// - `owner`: owner of the repo
5196    /// - `repo`: name of the repo
5197    /// - `id`: the milestone to delete, identified by ID and if not available by name
5198    pub async fn issue_delete_milestone(
5199        &self,
5200        owner: &str,
5201        repo: &str,
5202        id: &str,
5203    ) -> Result<(), ForgejoError> {
5204        let request = self
5205            .delete(&format!("repos/{owner}/{repo}/milestones/{id}"))
5206            .build()?;
5207        let response = self.execute(request).await?;
5208        match response.status().as_u16() {
5209            204 => Ok(()),
5210            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5211        }
5212    }
5213
5214    /// Update a milestone
5215    ///
5216    /// - `owner`: owner of the repo
5217    /// - `repo`: name of the repo
5218    /// - `id`: the milestone to edit, identified by ID and if not available by name
5219    /// - `body`: See [`EditMilestoneOption`]
5220    pub async fn issue_edit_milestone(
5221        &self,
5222        owner: &str,
5223        repo: &str,
5224        id: &str,
5225        body: EditMilestoneOption,
5226    ) -> Result<Milestone, ForgejoError> {
5227        let request = self
5228            .patch(&format!("repos/{owner}/{repo}/milestones/{id}"))
5229            .json(&body)
5230            .build()?;
5231        let response = self.execute(request).await?;
5232        match response.status().as_u16() {
5233            200 => Ok(response.json().await?),
5234            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5235        }
5236    }
5237
5238    /// Sync a mirrored repository
5239    ///
5240    /// - `owner`: owner of the repo to sync
5241    /// - `repo`: name of the repo to sync
5242    pub async fn repo_mirror_sync(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
5243        let request = self
5244            .post(&format!("repos/{owner}/{repo}/mirror-sync"))
5245            .build()?;
5246        let response = self.execute(request).await?;
5247        match response.status().as_u16() {
5248            200 => Ok(()),
5249            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5250        }
5251    }
5252
5253    /// Returns if new Issue Pins are allowed
5254    ///
5255    /// - `owner`: owner of the repo
5256    /// - `repo`: name of the repo
5257    pub async fn repo_new_pin_allowed(
5258        &self,
5259        owner: &str,
5260        repo: &str,
5261    ) -> Result<NewIssuePinsAllowed, ForgejoError> {
5262        let request = self
5263            .get(&format!("repos/{owner}/{repo}/new_pin_allowed"))
5264            .build()?;
5265        let response = self.execute(request).await?;
5266        match response.status().as_u16() {
5267            200 => Ok(response.json().await?),
5268            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5269        }
5270    }
5271
5272    /// List users's notification threads on a specific repo
5273    ///
5274    /// - `owner`: owner of the repo
5275    /// - `repo`: name of the repo
5276    pub async fn notify_get_repo_list(
5277        &self,
5278        owner: &str,
5279        repo: &str,
5280        query: NotifyGetRepoListQuery,
5281    ) -> Result<(NotificationThreadListHeaders, Vec<NotificationThread>), ForgejoError> {
5282        let request = self
5283            .get(&format!("repos/{owner}/{repo}/notifications?{query}"))
5284            .build()?;
5285        let response = self.execute(request).await?;
5286        match response.status().as_u16() {
5287            200 => Ok((response.headers().try_into()?, response.json().await?)),
5288            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5289        }
5290    }
5291
5292    /// Mark notification threads as read, pinned or unread on a specific repo
5293    ///
5294    /// - `owner`: owner of the repo
5295    /// - `repo`: name of the repo
5296    pub async fn notify_read_repo_list(
5297        &self,
5298        owner: &str,
5299        repo: &str,
5300        query: NotifyReadRepoListQuery,
5301    ) -> Result<(NotificationThreadListHeaders, Vec<NotificationThread>), ForgejoError> {
5302        let request = self
5303            .put(&format!("repos/{owner}/{repo}/notifications?{query}"))
5304            .build()?;
5305        let response = self.execute(request).await?;
5306        match response.status().as_u16() {
5307            205 => Ok((response.headers().try_into()?, response.json().await?)),
5308            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5309        }
5310    }
5311
5312    /// List a repo's pull requests
5313    ///
5314    /// - `owner`: Owner of the repo
5315    /// - `repo`: Name of the repo
5316    pub async fn repo_list_pull_requests(
5317        &self,
5318        owner: &str,
5319        repo: &str,
5320        query: RepoListPullRequestsQuery,
5321    ) -> Result<(PullRequestListHeaders, Vec<PullRequest>), ForgejoError> {
5322        let request = self
5323            .get(&format!("repos/{owner}/{repo}/pulls?{query}"))
5324            .build()?;
5325        let response = self.execute(request).await?;
5326        match response.status().as_u16() {
5327            200 => Ok((response.headers().try_into()?, response.json().await?)),
5328            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5329        }
5330    }
5331
5332    /// Create a pull request
5333    ///
5334    /// - `owner`: owner of the repo
5335    /// - `repo`: name of the repo
5336    /// - `body`: See [`CreatePullRequestOption`]
5337    pub async fn repo_create_pull_request(
5338        &self,
5339        owner: &str,
5340        repo: &str,
5341        body: CreatePullRequestOption,
5342    ) -> Result<PullRequest, ForgejoError> {
5343        let request = self
5344            .post(&format!("repos/{owner}/{repo}/pulls"))
5345            .json(&body)
5346            .build()?;
5347        let response = self.execute(request).await?;
5348        match response.status().as_u16() {
5349            201 => Ok(response.json().await?),
5350            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5351        }
5352    }
5353
5354    /// List a repo's pinned pull requests
5355    ///
5356    /// - `owner`: owner of the repo
5357    /// - `repo`: name of the repo
5358    pub async fn repo_list_pinned_pull_requests(
5359        &self,
5360        owner: &str,
5361        repo: &str,
5362    ) -> Result<(PullRequestListHeaders, Vec<PullRequest>), ForgejoError> {
5363        let request = self
5364            .get(&format!("repos/{owner}/{repo}/pulls/pinned"))
5365            .build()?;
5366        let response = self.execute(request).await?;
5367        match response.status().as_u16() {
5368            200 => Ok((response.headers().try_into()?, response.json().await?)),
5369            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5370        }
5371    }
5372
5373    /// Get a pull request by base and head
5374    ///
5375    /// - `owner`: owner of the repo
5376    /// - `repo`: name of the repo
5377    /// - `base`: base of the pull request to get
5378    /// - `head`: head of the pull request to get
5379    pub async fn repo_get_pull_request_by_base_head(
5380        &self,
5381        owner: &str,
5382        repo: &str,
5383        base: &str,
5384        head: &str,
5385    ) -> Result<PullRequest, ForgejoError> {
5386        let request = self
5387            .get(&format!("repos/{owner}/{repo}/pulls/{base}/{head}"))
5388            .build()?;
5389        let response = self.execute(request).await?;
5390        match response.status().as_u16() {
5391            200 => Ok(response.json().await?),
5392            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5393        }
5394    }
5395
5396    /// Get a pull request
5397    ///
5398    /// - `owner`: owner of the repo
5399    /// - `repo`: name of the repo
5400    /// - `index`: index of the pull request to get
5401    pub async fn repo_get_pull_request(
5402        &self,
5403        owner: &str,
5404        repo: &str,
5405        index: u64,
5406    ) -> Result<PullRequest, ForgejoError> {
5407        let request = self
5408            .get(&format!("repos/{owner}/{repo}/pulls/{index}"))
5409            .build()?;
5410        let response = self.execute(request).await?;
5411        match response.status().as_u16() {
5412            200 => Ok(response.json().await?),
5413            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5414        }
5415    }
5416
5417    /// Update a pull request. If using deadline only the date will be taken into account, and time of day ignored.
5418    ///
5419    /// - `owner`: owner of the repo
5420    /// - `repo`: name of the repo
5421    /// - `index`: index of the pull request to edit
5422    /// - `body`: See [`EditPullRequestOption`]
5423    pub async fn repo_edit_pull_request(
5424        &self,
5425        owner: &str,
5426        repo: &str,
5427        index: u64,
5428        body: EditPullRequestOption,
5429    ) -> Result<PullRequest, ForgejoError> {
5430        let request = self
5431            .patch(&format!("repos/{owner}/{repo}/pulls/{index}"))
5432            .json(&body)
5433            .build()?;
5434        let response = self.execute(request).await?;
5435        match response.status().as_u16() {
5436            201 => Ok(response.json().await?),
5437            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5438        }
5439    }
5440
5441    /// Get a pull request diff or patch
5442    ///
5443    /// - `owner`: owner of the repo
5444    /// - `repo`: name of the repo
5445    /// - `index`: index of the pull request to get
5446    /// - `diffType`: whether the output is diff or patch
5447    pub async fn repo_download_pull_diff_or_patch(
5448        &self,
5449        owner: &str,
5450        repo: &str,
5451        index: u64,
5452        diff_type: &str,
5453        query: RepoDownloadPullDiffOrPatchQuery,
5454    ) -> Result<String, ForgejoError> {
5455        let request = self
5456            .get(&format!(
5457                "repos/{owner}/{repo}/pulls/{index}.{diff_type}?{query}"
5458            ))
5459            .build()?;
5460        let response = self.execute(request).await?;
5461        match response.status().as_u16() {
5462            200 => Ok(response.text().await?),
5463            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5464        }
5465    }
5466
5467    /// Get commits for a pull request
5468    ///
5469    /// - `owner`: owner of the repo
5470    /// - `repo`: name of the repo
5471    /// - `index`: index of the pull request to get
5472    pub async fn repo_get_pull_request_commits(
5473        &self,
5474        owner: &str,
5475        repo: &str,
5476        index: u64,
5477        query: RepoGetPullRequestCommitsQuery,
5478    ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> {
5479        let request = self
5480            .get(&format!(
5481                "repos/{owner}/{repo}/pulls/{index}/commits?{query}"
5482            ))
5483            .build()?;
5484        let response = self.execute(request).await?;
5485        match response.status().as_u16() {
5486            200 => Ok((response.headers().try_into()?, response.json().await?)),
5487            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5488        }
5489    }
5490
5491    /// Get changed files for a pull request
5492    ///
5493    /// - `owner`: owner of the repo
5494    /// - `repo`: name of the repo
5495    /// - `index`: index of the pull request to get
5496    pub async fn repo_get_pull_request_files(
5497        &self,
5498        owner: &str,
5499        repo: &str,
5500        index: u64,
5501        query: RepoGetPullRequestFilesQuery,
5502    ) -> Result<(ChangedFileListHeaders, Vec<ChangedFile>), ForgejoError> {
5503        let request = self
5504            .get(&format!("repos/{owner}/{repo}/pulls/{index}/files?{query}"))
5505            .build()?;
5506        let response = self.execute(request).await?;
5507        match response.status().as_u16() {
5508            200 => Ok((response.headers().try_into()?, response.json().await?)),
5509            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5510        }
5511    }
5512
5513    /// Check if a pull request has been merged
5514    ///
5515    /// - `owner`: owner of the repo
5516    /// - `repo`: name of the repo
5517    /// - `index`: index of the pull request
5518    pub async fn repo_pull_request_is_merged(
5519        &self,
5520        owner: &str,
5521        repo: &str,
5522        index: u64,
5523    ) -> Result<(), ForgejoError> {
5524        let request = self
5525            .get(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
5526            .build()?;
5527        let response = self.execute(request).await?;
5528        match response.status().as_u16() {
5529            204 => Ok(()),
5530            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5531        }
5532    }
5533
5534    /// Merge a pull request
5535    ///
5536    /// - `owner`: owner of the repo
5537    /// - `repo`: name of the repo
5538    /// - `index`: index of the pull request to merge
5539    /// - `body`: See [`MergePullRequestOption`]
5540    pub async fn repo_merge_pull_request(
5541        &self,
5542        owner: &str,
5543        repo: &str,
5544        index: u64,
5545        body: MergePullRequestOption,
5546    ) -> Result<(), ForgejoError> {
5547        let request = self
5548            .post(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
5549            .json(&body)
5550            .build()?;
5551        let response = self.execute(request).await?;
5552        match response.status().as_u16() {
5553            200 => Ok(()),
5554            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5555        }
5556    }
5557
5558    /// Cancel the scheduled auto merge for the given pull request
5559    ///
5560    /// - `owner`: owner of the repo
5561    /// - `repo`: name of the repo
5562    /// - `index`: index of the pull request to merge
5563    pub async fn repo_cancel_scheduled_auto_merge(
5564        &self,
5565        owner: &str,
5566        repo: &str,
5567        index: u64,
5568    ) -> Result<(), ForgejoError> {
5569        let request = self
5570            .delete(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
5571            .build()?;
5572        let response = self.execute(request).await?;
5573        match response.status().as_u16() {
5574            204 => Ok(()),
5575            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5576        }
5577    }
5578
5579    /// create review requests for a pull request
5580    ///
5581    /// - `owner`: owner of the repo
5582    /// - `repo`: name of the repo
5583    /// - `index`: index of the pull request
5584    /// - `body`: See [`PullReviewRequestOptions`]
5585    pub async fn repo_create_pull_review_requests(
5586        &self,
5587        owner: &str,
5588        repo: &str,
5589        index: u64,
5590        body: PullReviewRequestOptions,
5591    ) -> Result<(PullReviewListHeaders, Vec<PullReview>), ForgejoError> {
5592        let request = self
5593            .post(&format!(
5594                "repos/{owner}/{repo}/pulls/{index}/requested_reviewers"
5595            ))
5596            .json(&body)
5597            .build()?;
5598        let response = self.execute(request).await?;
5599        match response.status().as_u16() {
5600            201 => Ok((response.headers().try_into()?, response.json().await?)),
5601            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5602        }
5603    }
5604
5605    /// cancel review requests for a pull request
5606    ///
5607    /// - `owner`: owner of the repo
5608    /// - `repo`: name of the repo
5609    /// - `index`: index of the pull request
5610    /// - `body`: See [`PullReviewRequestOptions`]
5611    pub async fn repo_delete_pull_review_requests(
5612        &self,
5613        owner: &str,
5614        repo: &str,
5615        index: u64,
5616        body: PullReviewRequestOptions,
5617    ) -> Result<(), ForgejoError> {
5618        let request = self
5619            .delete(&format!(
5620                "repos/{owner}/{repo}/pulls/{index}/requested_reviewers"
5621            ))
5622            .json(&body)
5623            .build()?;
5624        let response = self.execute(request).await?;
5625        match response.status().as_u16() {
5626            204 => Ok(()),
5627            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5628        }
5629    }
5630
5631    /// List all reviews for a pull request
5632    ///
5633    /// - `owner`: owner of the repo
5634    /// - `repo`: name of the repo
5635    /// - `index`: index of the pull request
5636    pub async fn repo_list_pull_reviews(
5637        &self,
5638        owner: &str,
5639        repo: &str,
5640        index: u64,
5641        query: RepoListPullReviewsQuery,
5642    ) -> Result<(PullReviewListHeaders, Vec<PullReview>), ForgejoError> {
5643        let request = self
5644            .get(&format!(
5645                "repos/{owner}/{repo}/pulls/{index}/reviews?{query}"
5646            ))
5647            .build()?;
5648        let response = self.execute(request).await?;
5649        match response.status().as_u16() {
5650            200 => Ok((response.headers().try_into()?, response.json().await?)),
5651            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5652        }
5653    }
5654
5655    /// Create a review to an pull request
5656    ///
5657    /// - `owner`: owner of the repo
5658    /// - `repo`: name of the repo
5659    /// - `index`: index of the pull request
5660    /// - `body`: See [`CreatePullReviewOptions`]
5661    pub async fn repo_create_pull_review(
5662        &self,
5663        owner: &str,
5664        repo: &str,
5665        index: u64,
5666        body: CreatePullReviewOptions,
5667    ) -> Result<PullReview, ForgejoError> {
5668        let request = self
5669            .post(&format!("repos/{owner}/{repo}/pulls/{index}/reviews"))
5670            .json(&body)
5671            .build()?;
5672        let response = self.execute(request).await?;
5673        match response.status().as_u16() {
5674            200 => Ok(response.json().await?),
5675            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5676        }
5677    }
5678
5679    /// Get a specific review for a pull request
5680    ///
5681    /// - `owner`: owner of the repo
5682    /// - `repo`: name of the repo
5683    /// - `index`: index of the pull request
5684    /// - `id`: id of the review
5685    pub async fn repo_get_pull_review(
5686        &self,
5687        owner: &str,
5688        repo: &str,
5689        index: u64,
5690        id: u64,
5691    ) -> Result<PullReview, ForgejoError> {
5692        let request = self
5693            .get(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
5694            .build()?;
5695        let response = self.execute(request).await?;
5696        match response.status().as_u16() {
5697            200 => Ok(response.json().await?),
5698            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5699        }
5700    }
5701
5702    /// Submit a pending review to an pull request
5703    ///
5704    /// - `owner`: owner of the repo
5705    /// - `repo`: name of the repo
5706    /// - `index`: index of the pull request
5707    /// - `id`: id of the review
5708    /// - `body`: See [`SubmitPullReviewOptions`]
5709    pub async fn repo_submit_pull_review(
5710        &self,
5711        owner: &str,
5712        repo: &str,
5713        index: u64,
5714        id: u64,
5715        body: SubmitPullReviewOptions,
5716    ) -> Result<PullReview, ForgejoError> {
5717        let request = self
5718            .post(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
5719            .json(&body)
5720            .build()?;
5721        let response = self.execute(request).await?;
5722        match response.status().as_u16() {
5723            200 => Ok(response.json().await?),
5724            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5725        }
5726    }
5727
5728    /// Delete a specific review from a pull request
5729    ///
5730    /// - `owner`: owner of the repo
5731    /// - `repo`: name of the repo
5732    /// - `index`: index of the pull request
5733    /// - `id`: id of the review
5734    pub async fn repo_delete_pull_review(
5735        &self,
5736        owner: &str,
5737        repo: &str,
5738        index: u64,
5739        id: u64,
5740    ) -> Result<(), ForgejoError> {
5741        let request = self
5742            .delete(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
5743            .build()?;
5744        let response = self.execute(request).await?;
5745        match response.status().as_u16() {
5746            204 => Ok(()),
5747            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5748        }
5749    }
5750
5751    /// Get a specific review for a pull request
5752    ///
5753    /// - `owner`: owner of the repo
5754    /// - `repo`: name of the repo
5755    /// - `index`: index of the pull request
5756    /// - `id`: id of the review
5757    pub async fn repo_get_pull_review_comments(
5758        &self,
5759        owner: &str,
5760        repo: &str,
5761        index: u64,
5762        id: u64,
5763    ) -> Result<Vec<PullReviewComment>, ForgejoError> {
5764        let request = self
5765            .get(&format!(
5766                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments"
5767            ))
5768            .build()?;
5769        let response = self.execute(request).await?;
5770        match response.status().as_u16() {
5771            200 => Ok(response.json().await?),
5772            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5773        }
5774    }
5775
5776    /// Add a new comment to a pull request review
5777    ///
5778    /// - `owner`: owner of the repo
5779    /// - `repo`: name of the repo
5780    /// - `index`: index of the pull request
5781    /// - `id`: id of the review
5782    /// - `body`: See [`serde_json::Value`]
5783    pub async fn repo_create_pull_review_comment(
5784        &self,
5785        owner: &str,
5786        repo: &str,
5787        index: u64,
5788        id: u64,
5789        body: serde_json::Value,
5790    ) -> Result<PullReviewComment, ForgejoError> {
5791        let request = self
5792            .post(&format!(
5793                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments"
5794            ))
5795            .json(&body)
5796            .build()?;
5797        let response = self.execute(request).await?;
5798        match response.status().as_u16() {
5799            200 => Ok(response.json().await?),
5800            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5801        }
5802    }
5803
5804    /// Get a pull review comment
5805    ///
5806    /// - `owner`: owner of the repo
5807    /// - `repo`: name of the repo
5808    /// - `index`: index of the pull request
5809    /// - `id`: id of the review
5810    /// - `comment`: id of the comment
5811    pub async fn repo_get_pull_review_comment(
5812        &self,
5813        owner: &str,
5814        repo: &str,
5815        index: u64,
5816        id: u64,
5817        comment: u64,
5818    ) -> Result<PullReviewComment, ForgejoError> {
5819        let request = self
5820            .get(&format!(
5821                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment}"
5822            ))
5823            .build()?;
5824        let response = self.execute(request).await?;
5825        match response.status().as_u16() {
5826            200 => Ok(response.json().await?),
5827            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5828        }
5829    }
5830
5831    /// Delete a pull review comment
5832    ///
5833    /// - `owner`: owner of the repo
5834    /// - `repo`: name of the repo
5835    /// - `index`: index of the pull request
5836    /// - `id`: id of the review
5837    /// - `comment`: id of the comment
5838    pub async fn repo_delete_pull_review_comment(
5839        &self,
5840        owner: &str,
5841        repo: &str,
5842        index: u64,
5843        id: u64,
5844        comment: u64,
5845    ) -> Result<(), ForgejoError> {
5846        let request = self
5847            .delete(&format!(
5848                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment}"
5849            ))
5850            .build()?;
5851        let response = self.execute(request).await?;
5852        match response.status().as_u16() {
5853            204 => Ok(()),
5854            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5855        }
5856    }
5857
5858    /// Dismiss a review for a pull request
5859    ///
5860    /// - `owner`: owner of the repo
5861    /// - `repo`: name of the repo
5862    /// - `index`: index of the pull request
5863    /// - `id`: id of the review
5864    /// - `body`: See [`DismissPullReviewOptions`]
5865    pub async fn repo_dismiss_pull_review(
5866        &self,
5867        owner: &str,
5868        repo: &str,
5869        index: u64,
5870        id: u64,
5871        body: DismissPullReviewOptions,
5872    ) -> Result<PullReview, ForgejoError> {
5873        let request = self
5874            .post(&format!(
5875                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals"
5876            ))
5877            .json(&body)
5878            .build()?;
5879        let response = self.execute(request).await?;
5880        match response.status().as_u16() {
5881            200 => Ok(response.json().await?),
5882            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5883        }
5884    }
5885
5886    /// Cancel to dismiss a review for a pull request
5887    ///
5888    /// - `owner`: owner of the repo
5889    /// - `repo`: name of the repo
5890    /// - `index`: index of the pull request
5891    /// - `id`: id of the review
5892    pub async fn repo_un_dismiss_pull_review(
5893        &self,
5894        owner: &str,
5895        repo: &str,
5896        index: u64,
5897        id: u64,
5898    ) -> Result<PullReview, ForgejoError> {
5899        let request = self
5900            .post(&format!(
5901                "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/undismissals"
5902            ))
5903            .build()?;
5904        let response = self.execute(request).await?;
5905        match response.status().as_u16() {
5906            200 => Ok(response.json().await?),
5907            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5908        }
5909    }
5910
5911    /// Merge PR's baseBranch into headBranch
5912    ///
5913    /// - `owner`: owner of the repo
5914    /// - `repo`: name of the repo
5915    /// - `index`: index of the pull request to get
5916    pub async fn repo_update_pull_request(
5917        &self,
5918        owner: &str,
5919        repo: &str,
5920        index: u64,
5921        query: RepoUpdatePullRequestQuery,
5922    ) -> Result<(), ForgejoError> {
5923        let request = self
5924            .post(&format!(
5925                "repos/{owner}/{repo}/pulls/{index}/update?{query}"
5926            ))
5927            .build()?;
5928        let response = self.execute(request).await?;
5929        match response.status().as_u16() {
5930            200 => Ok(()),
5931            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5932        }
5933    }
5934
5935    /// Get all push mirrors of the repository
5936    ///
5937    /// - `owner`: owner of the repo
5938    /// - `repo`: name of the repo
5939    pub async fn repo_list_push_mirrors(
5940        &self,
5941        owner: &str,
5942        repo: &str,
5943        query: RepoListPushMirrorsQuery,
5944    ) -> Result<(PushMirrorListHeaders, Vec<PushMirror>), ForgejoError> {
5945        let request = self
5946            .get(&format!("repos/{owner}/{repo}/push_mirrors?{query}"))
5947            .build()?;
5948        let response = self.execute(request).await?;
5949        match response.status().as_u16() {
5950            200 => Ok((response.headers().try_into()?, response.json().await?)),
5951            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5952        }
5953    }
5954
5955    /// add a push mirror to the repository
5956    ///
5957    /// - `owner`: owner of the repo
5958    /// - `repo`: name of the repo
5959    /// - `body`: See [`CreatePushMirrorOption`]
5960    pub async fn repo_add_push_mirror(
5961        &self,
5962        owner: &str,
5963        repo: &str,
5964        body: CreatePushMirrorOption,
5965    ) -> Result<PushMirror, ForgejoError> {
5966        let request = self
5967            .post(&format!("repos/{owner}/{repo}/push_mirrors"))
5968            .json(&body)
5969            .build()?;
5970        let response = self.execute(request).await?;
5971        match response.status().as_u16() {
5972            200 => Ok(response.json().await?),
5973            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5974        }
5975    }
5976
5977    /// Sync all push mirrored repository
5978    ///
5979    /// - `owner`: owner of the repo to sync
5980    /// - `repo`: name of the repo to sync
5981    pub async fn repo_push_mirror_sync(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
5982        let request = self
5983            .post(&format!("repos/{owner}/{repo}/push_mirrors-sync"))
5984            .build()?;
5985        let response = self.execute(request).await?;
5986        match response.status().as_u16() {
5987            200 => Ok(()),
5988            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
5989        }
5990    }
5991
5992    /// Get push mirror of the repository by remoteName
5993    ///
5994    /// - `owner`: owner of the repo
5995    /// - `repo`: name of the repo
5996    /// - `name`: remote name of push mirror
5997    pub async fn repo_get_push_mirror_by_remote_name(
5998        &self,
5999        owner: &str,
6000        repo: &str,
6001        name: &str,
6002    ) -> Result<PushMirror, ForgejoError> {
6003        let request = self
6004            .get(&format!("repos/{owner}/{repo}/push_mirrors/{name}"))
6005            .build()?;
6006        let response = self.execute(request).await?;
6007        match response.status().as_u16() {
6008            200 => Ok(response.json().await?),
6009            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6010        }
6011    }
6012
6013    /// deletes a push mirror from a repository by remoteName
6014    ///
6015    /// - `owner`: owner of the repo
6016    /// - `repo`: name of the repo
6017    /// - `name`: remote name of the pushMirror
6018    pub async fn repo_delete_push_mirror(
6019        &self,
6020        owner: &str,
6021        repo: &str,
6022        name: &str,
6023    ) -> Result<(), ForgejoError> {
6024        let request = self
6025            .delete(&format!("repos/{owner}/{repo}/push_mirrors/{name}"))
6026            .build()?;
6027        let response = self.execute(request).await?;
6028        match response.status().as_u16() {
6029            204 => Ok(()),
6030            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6031        }
6032    }
6033
6034    /// Get a file from a repository
6035    ///
6036    /// - `owner`: owner of the repo
6037    /// - `repo`: name of the repo
6038    /// - `filepath`: filepath of the file to get
6039    pub async fn repo_get_raw_file(
6040        &self,
6041        owner: &str,
6042        repo: &str,
6043        filepath: &str,
6044        query: RepoGetRawFileQuery,
6045    ) -> Result<Vec<u8>, ForgejoError> {
6046        let request = self
6047            .get(&format!("repos/{owner}/{repo}/raw/{filepath}?{query}"))
6048            .build()?;
6049        let response = self.execute(request).await?;
6050        match response.status().as_u16() {
6051            200 => Ok(response.bytes().await?[..].to_vec()),
6052            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6053        }
6054    }
6055
6056    /// List a repo's releases
6057    ///
6058    /// - `owner`: owner of the repo
6059    /// - `repo`: name of the repo
6060    pub async fn repo_list_releases(
6061        &self,
6062        owner: &str,
6063        repo: &str,
6064        query: RepoListReleasesQuery,
6065    ) -> Result<(ReleaseListHeaders, Vec<Release>), ForgejoError> {
6066        let request = self
6067            .get(&format!("repos/{owner}/{repo}/releases?{query}"))
6068            .build()?;
6069        let response = self.execute(request).await?;
6070        match response.status().as_u16() {
6071            200 => Ok((response.headers().try_into()?, response.json().await?)),
6072            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6073        }
6074    }
6075
6076    /// Create a release
6077    ///
6078    /// - `owner`: owner of the repo
6079    /// - `repo`: name of the repo
6080    /// - `body`: See [`CreateReleaseOption`]
6081    pub async fn repo_create_release(
6082        &self,
6083        owner: &str,
6084        repo: &str,
6085        body: CreateReleaseOption,
6086    ) -> Result<Release, ForgejoError> {
6087        let request = self
6088            .post(&format!("repos/{owner}/{repo}/releases"))
6089            .json(&body)
6090            .build()?;
6091        let response = self.execute(request).await?;
6092        match response.status().as_u16() {
6093            201 => Ok(response.json().await?),
6094            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6095        }
6096    }
6097
6098    /// Gets the most recent non-prerelease, non-draft release of a repository, sorted by created_at
6099    ///
6100    /// - `owner`: owner of the repo
6101    /// - `repo`: name of the repo
6102    pub async fn repo_get_latest_release(
6103        &self,
6104        owner: &str,
6105        repo: &str,
6106    ) -> Result<Release, ForgejoError> {
6107        let request = self
6108            .get(&format!("repos/{owner}/{repo}/releases/latest"))
6109            .build()?;
6110        let response = self.execute(request).await?;
6111        match response.status().as_u16() {
6112            200 => Ok(response.json().await?),
6113            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6114        }
6115    }
6116
6117    /// Get a release by tag name
6118    ///
6119    /// - `owner`: owner of the repo
6120    /// - `repo`: name of the repo
6121    /// - `tag`: tag name of the release to get
6122    pub async fn repo_get_release_by_tag(
6123        &self,
6124        owner: &str,
6125        repo: &str,
6126        tag: &str,
6127    ) -> Result<Release, ForgejoError> {
6128        let request = self
6129            .get(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
6130            .build()?;
6131        let response = self.execute(request).await?;
6132        match response.status().as_u16() {
6133            200 => Ok(response.json().await?),
6134            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6135        }
6136    }
6137
6138    /// Delete a release by tag name
6139    ///
6140    /// - `owner`: owner of the repo
6141    /// - `repo`: name of the repo
6142    /// - `tag`: tag name of the release to delete
6143    pub async fn repo_delete_release_by_tag(
6144        &self,
6145        owner: &str,
6146        repo: &str,
6147        tag: &str,
6148    ) -> Result<(), ForgejoError> {
6149        let request = self
6150            .delete(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
6151            .build()?;
6152        let response = self.execute(request).await?;
6153        match response.status().as_u16() {
6154            204 => Ok(()),
6155            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6156        }
6157    }
6158
6159    /// Get a release
6160    ///
6161    /// - `owner`: owner of the repo
6162    /// - `repo`: name of the repo
6163    /// - `id`: id of the release to get
6164    pub async fn repo_get_release(
6165        &self,
6166        owner: &str,
6167        repo: &str,
6168        id: u64,
6169    ) -> Result<Release, ForgejoError> {
6170        let request = self
6171            .get(&format!("repos/{owner}/{repo}/releases/{id}"))
6172            .build()?;
6173        let response = self.execute(request).await?;
6174        match response.status().as_u16() {
6175            200 => Ok(response.json().await?),
6176            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6177        }
6178    }
6179
6180    /// Delete a release
6181    ///
6182    /// - `owner`: owner of the repo
6183    /// - `repo`: name of the repo
6184    /// - `id`: id of the release to delete
6185    pub async fn repo_delete_release(
6186        &self,
6187        owner: &str,
6188        repo: &str,
6189        id: u64,
6190    ) -> Result<(), ForgejoError> {
6191        let request = self
6192            .delete(&format!("repos/{owner}/{repo}/releases/{id}"))
6193            .build()?;
6194        let response = self.execute(request).await?;
6195        match response.status().as_u16() {
6196            204 => Ok(()),
6197            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6198        }
6199    }
6200
6201    /// Update a release
6202    ///
6203    /// - `owner`: owner of the repo
6204    /// - `repo`: name of the repo
6205    /// - `id`: id of the release to edit
6206    /// - `body`: See [`EditReleaseOption`]
6207    pub async fn repo_edit_release(
6208        &self,
6209        owner: &str,
6210        repo: &str,
6211        id: u64,
6212        body: EditReleaseOption,
6213    ) -> Result<Release, ForgejoError> {
6214        let request = self
6215            .patch(&format!("repos/{owner}/{repo}/releases/{id}"))
6216            .json(&body)
6217            .build()?;
6218        let response = self.execute(request).await?;
6219        match response.status().as_u16() {
6220            200 => Ok(response.json().await?),
6221            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6222        }
6223    }
6224
6225    /// List release's attachments
6226    ///
6227    /// - `owner`: owner of the repo
6228    /// - `repo`: name of the repo
6229    /// - `id`: id of the release
6230    pub async fn repo_list_release_attachments(
6231        &self,
6232        owner: &str,
6233        repo: &str,
6234        id: u64,
6235    ) -> Result<Vec<Attachment>, ForgejoError> {
6236        let request = self
6237            .get(&format!("repos/{owner}/{repo}/releases/{id}/assets"))
6238            .build()?;
6239        let response = self.execute(request).await?;
6240        match response.status().as_u16() {
6241            200 => Ok(response.json().await?),
6242            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6243        }
6244    }
6245
6246    /// Create a release attachment
6247    ///
6248    /// - `owner`: owner of the repo
6249    /// - `repo`: name of the repo
6250    /// - `id`: id of the release
6251    /// - `attachment`: attachment to upload (this parameter is incompatible with `external_url`)
6252    /// - `external_url`: url to external asset (this parameter is incompatible with `attachment`)
6253    pub async fn repo_create_release_attachment(
6254        &self,
6255        owner: &str,
6256        repo: &str,
6257        id: u64,
6258        attachment: Option<Vec<u8>>,
6259        external_url: Option<Vec<u8>>,
6260        query: RepoCreateReleaseAttachmentQuery,
6261    ) -> Result<Attachment, ForgejoError> {
6262        let builder = self.post(&format!(
6263            "repos/{owner}/{repo}/releases/{id}/assets?{query}"
6264        ));
6265        let builder = match attachment {
6266            Some(attachment) => builder.multipart(
6267                reqwest::multipart::Form::new().part(
6268                    "attachment",
6269                    reqwest::multipart::Part::bytes(attachment)
6270                        .file_name("file")
6271                        .mime_str("*/*")
6272                        .unwrap(),
6273                ),
6274            ),
6275            None => builder,
6276        };
6277        let builder = match external_url {
6278            Some(external_url) => builder.multipart(
6279                reqwest::multipart::Form::new().part(
6280                    "attachment",
6281                    reqwest::multipart::Part::bytes(external_url)
6282                        .file_name("file")
6283                        .mime_str("*/*")
6284                        .unwrap(),
6285                ),
6286            ),
6287            None => builder,
6288        };
6289        let request = builder.build()?;
6290        let response = self.execute(request).await?;
6291        match response.status().as_u16() {
6292            201 => Ok(response.json().await?),
6293            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6294        }
6295    }
6296
6297    /// Get a release attachment
6298    ///
6299    /// - `owner`: owner of the repo
6300    /// - `repo`: name of the repo
6301    /// - `id`: id of the release
6302    /// - `attachment_id`: id of the attachment to get
6303    pub async fn repo_get_release_attachment(
6304        &self,
6305        owner: &str,
6306        repo: &str,
6307        id: u64,
6308        attachment_id: u64,
6309    ) -> Result<Attachment, ForgejoError> {
6310        let request = self
6311            .get(&format!(
6312                "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
6313            ))
6314            .build()?;
6315        let response = self.execute(request).await?;
6316        match response.status().as_u16() {
6317            200 => Ok(response.json().await?),
6318            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6319        }
6320    }
6321
6322    /// Delete a release attachment
6323    ///
6324    /// - `owner`: owner of the repo
6325    /// - `repo`: name of the repo
6326    /// - `id`: id of the release
6327    /// - `attachment_id`: id of the attachment to delete
6328    pub async fn repo_delete_release_attachment(
6329        &self,
6330        owner: &str,
6331        repo: &str,
6332        id: u64,
6333        attachment_id: u64,
6334    ) -> Result<(), ForgejoError> {
6335        let request = self
6336            .delete(&format!(
6337                "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
6338            ))
6339            .build()?;
6340        let response = self.execute(request).await?;
6341        match response.status().as_u16() {
6342            204 => Ok(()),
6343            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6344        }
6345    }
6346
6347    /// Edit a release attachment
6348    ///
6349    /// - `owner`: owner of the repo
6350    /// - `repo`: name of the repo
6351    /// - `id`: id of the release
6352    /// - `attachment_id`: id of the attachment to edit
6353    /// - `body`: See [`EditAttachmentOptions`]
6354    pub async fn repo_edit_release_attachment(
6355        &self,
6356        owner: &str,
6357        repo: &str,
6358        id: u64,
6359        attachment_id: u64,
6360        body: EditAttachmentOptions,
6361    ) -> Result<Attachment, ForgejoError> {
6362        let request = self
6363            .patch(&format!(
6364                "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
6365            ))
6366            .json(&body)
6367            .build()?;
6368        let response = self.execute(request).await?;
6369        match response.status().as_u16() {
6370            201 => Ok(response.json().await?),
6371            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6372        }
6373    }
6374
6375    /// Return all users that can be requested to review in this repo
6376    ///
6377    /// - `owner`: owner of the repo
6378    /// - `repo`: name of the repo
6379    pub async fn repo_get_reviewers(
6380        &self,
6381        owner: &str,
6382        repo: &str,
6383    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
6384        let request = self
6385            .get(&format!("repos/{owner}/{repo}/reviewers"))
6386            .build()?;
6387        let response = self.execute(request).await?;
6388        match response.status().as_u16() {
6389            200 => Ok((response.headers().try_into()?, response.json().await?)),
6390            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6391        }
6392    }
6393
6394    /// Get signing-key.gpg for given repository
6395    ///
6396    /// - `owner`: owner of the repo
6397    /// - `repo`: name of the repo
6398    pub async fn repo_signing_key(&self, owner: &str, repo: &str) -> Result<String, ForgejoError> {
6399        let request = self
6400            .get(&format!("repos/{owner}/{repo}/signing-key.gpg"))
6401            .build()?;
6402        let response = self.execute(request).await?;
6403        match response.status().as_u16() {
6404            200 => Ok(response.text().await?),
6405            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6406        }
6407    }
6408
6409    /// List a repo's stargazers
6410    ///
6411    /// - `owner`: owner of the repo
6412    /// - `repo`: name of the repo
6413    pub async fn repo_list_stargazers(
6414        &self,
6415        owner: &str,
6416        repo: &str,
6417        query: RepoListStargazersQuery,
6418    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
6419        let request = self
6420            .get(&format!("repos/{owner}/{repo}/stargazers?{query}"))
6421            .build()?;
6422        let response = self.execute(request).await?;
6423        match response.status().as_u16() {
6424            200 => Ok((response.headers().try_into()?, response.json().await?)),
6425            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6426        }
6427    }
6428
6429    /// Get a commit's statuses
6430    ///
6431    /// - `owner`: owner of the repo
6432    /// - `repo`: name of the repo
6433    /// - `sha`: sha of the commit
6434    pub async fn repo_list_statuses(
6435        &self,
6436        owner: &str,
6437        repo: &str,
6438        sha: &str,
6439        query: RepoListStatusesQuery,
6440    ) -> Result<(CommitStatusListHeaders, Vec<CommitStatus>), ForgejoError> {
6441        let request = self
6442            .get(&format!("repos/{owner}/{repo}/statuses/{sha}?{query}"))
6443            .build()?;
6444        let response = self.execute(request).await?;
6445        match response.status().as_u16() {
6446            200 => Ok((response.headers().try_into()?, response.json().await?)),
6447            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6448        }
6449    }
6450
6451    /// Create a commit status
6452    ///
6453    /// - `owner`: owner of the repo
6454    /// - `repo`: name of the repo
6455    /// - `sha`: sha of the commit
6456    /// - `body`: See [`CreateStatusOption`]
6457    pub async fn repo_create_status(
6458        &self,
6459        owner: &str,
6460        repo: &str,
6461        sha: &str,
6462        body: CreateStatusOption,
6463    ) -> Result<CommitStatus, ForgejoError> {
6464        let request = self
6465            .post(&format!("repos/{owner}/{repo}/statuses/{sha}"))
6466            .json(&body)
6467            .build()?;
6468        let response = self.execute(request).await?;
6469        match response.status().as_u16() {
6470            201 => Ok(response.json().await?),
6471            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6472        }
6473    }
6474
6475    /// List a repo's watchers
6476    ///
6477    /// - `owner`: owner of the repo
6478    /// - `repo`: name of the repo
6479    pub async fn repo_list_subscribers(
6480        &self,
6481        owner: &str,
6482        repo: &str,
6483        query: RepoListSubscribersQuery,
6484    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
6485        let request = self
6486            .get(&format!("repos/{owner}/{repo}/subscribers?{query}"))
6487            .build()?;
6488        let response = self.execute(request).await?;
6489        match response.status().as_u16() {
6490            200 => Ok((response.headers().try_into()?, response.json().await?)),
6491            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6492        }
6493    }
6494
6495    /// Check if the current user is watching a repo
6496    ///
6497    /// - `owner`: owner of the repo
6498    /// - `repo`: name of the repo
6499    pub async fn user_current_check_subscription(
6500        &self,
6501        owner: &str,
6502        repo: &str,
6503    ) -> Result<WatchInfo, ForgejoError> {
6504        let request = self
6505            .get(&format!("repos/{owner}/{repo}/subscription"))
6506            .build()?;
6507        let response = self.execute(request).await?;
6508        match response.status().as_u16() {
6509            200 => Ok(response.json().await?),
6510            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6511        }
6512    }
6513
6514    /// Watch a repo
6515    ///
6516    /// - `owner`: owner of the repo
6517    /// - `repo`: name of the repo
6518    pub async fn user_current_put_subscription(
6519        &self,
6520        owner: &str,
6521        repo: &str,
6522    ) -> Result<WatchInfo, ForgejoError> {
6523        let request = self
6524            .put(&format!("repos/{owner}/{repo}/subscription"))
6525            .build()?;
6526        let response = self.execute(request).await?;
6527        match response.status().as_u16() {
6528            200 => Ok(response.json().await?),
6529            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6530        }
6531    }
6532
6533    /// Unwatch a repo
6534    ///
6535    /// - `owner`: owner of the repo
6536    /// - `repo`: name of the repo
6537    pub async fn user_current_delete_subscription(
6538        &self,
6539        owner: &str,
6540        repo: &str,
6541    ) -> Result<(), ForgejoError> {
6542        let request = self
6543            .delete(&format!("repos/{owner}/{repo}/subscription"))
6544            .build()?;
6545        let response = self.execute(request).await?;
6546        match response.status().as_u16() {
6547            204 => Ok(()),
6548            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6549        }
6550    }
6551
6552    /// List tag protections for a repository
6553    ///
6554    /// - `owner`: owner of the repo
6555    /// - `repo`: name of the repo
6556    pub async fn repo_list_tag_protection(
6557        &self,
6558        owner: &str,
6559        repo: &str,
6560    ) -> Result<Vec<TagProtection>, ForgejoError> {
6561        let request = self
6562            .get(&format!("repos/{owner}/{repo}/tag_protections"))
6563            .build()?;
6564        let response = self.execute(request).await?;
6565        match response.status().as_u16() {
6566            200 => Ok(response.json().await?),
6567            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6568        }
6569    }
6570
6571    /// Create a tag protections for a repository
6572    ///
6573    /// - `owner`: owner of the repo
6574    /// - `repo`: name of the repo
6575    /// - `body`: See [`CreateTagProtectionOption`]
6576    pub async fn repo_create_tag_protection(
6577        &self,
6578        owner: &str,
6579        repo: &str,
6580        body: CreateTagProtectionOption,
6581    ) -> Result<TagProtection, ForgejoError> {
6582        let request = self
6583            .post(&format!("repos/{owner}/{repo}/tag_protections"))
6584            .json(&body)
6585            .build()?;
6586        let response = self.execute(request).await?;
6587        match response.status().as_u16() {
6588            201 => Ok(response.json().await?),
6589            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6590        }
6591    }
6592
6593    /// Get a specific tag protection for the repository
6594    ///
6595    /// - `owner`: owner of the repo
6596    /// - `repo`: name of the repo
6597    /// - `id`: id of the tag protect to get
6598    pub async fn repo_get_tag_protection(
6599        &self,
6600        owner: &str,
6601        repo: &str,
6602        id: u32,
6603    ) -> Result<TagProtection, ForgejoError> {
6604        let request = self
6605            .get(&format!("repos/{owner}/{repo}/tag_protections/{id}"))
6606            .build()?;
6607        let response = self.execute(request).await?;
6608        match response.status().as_u16() {
6609            200 => Ok(response.json().await?),
6610            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6611        }
6612    }
6613
6614    /// Delete a specific tag protection for the repository
6615    ///
6616    /// - `owner`: owner of the repo
6617    /// - `repo`: name of the repo
6618    /// - `id`: id of protected tag
6619    pub async fn repo_delete_tag_protection(
6620        &self,
6621        owner: &str,
6622        repo: &str,
6623        id: u32,
6624    ) -> Result<(), ForgejoError> {
6625        let request = self
6626            .delete(&format!("repos/{owner}/{repo}/tag_protections/{id}"))
6627            .build()?;
6628        let response = self.execute(request).await?;
6629        match response.status().as_u16() {
6630            204 => Ok(()),
6631            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6632        }
6633    }
6634
6635    /// Edit a tag protections for a repository. Only fields that are set will be changed
6636    ///
6637    /// - `owner`: owner of the repo
6638    /// - `repo`: name of the repo
6639    /// - `id`: id of protected tag
6640    /// - `body`: See [`EditTagProtectionOption`]
6641    pub async fn repo_edit_tag_protection(
6642        &self,
6643        owner: &str,
6644        repo: &str,
6645        id: u32,
6646        body: EditTagProtectionOption,
6647    ) -> Result<TagProtection, ForgejoError> {
6648        let request = self
6649            .patch(&format!("repos/{owner}/{repo}/tag_protections/{id}"))
6650            .json(&body)
6651            .build()?;
6652        let response = self.execute(request).await?;
6653        match response.status().as_u16() {
6654            200 => Ok(response.json().await?),
6655            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6656        }
6657    }
6658
6659    /// List a repository's tags
6660    ///
6661    /// - `owner`: owner of the repo
6662    /// - `repo`: name of the repo
6663    pub async fn repo_list_tags(
6664        &self,
6665        owner: &str,
6666        repo: &str,
6667        query: RepoListTagsQuery,
6668    ) -> Result<(TagListHeaders, Vec<Tag>), ForgejoError> {
6669        let request = self
6670            .get(&format!("repos/{owner}/{repo}/tags?{query}"))
6671            .build()?;
6672        let response = self.execute(request).await?;
6673        match response.status().as_u16() {
6674            200 => Ok((response.headers().try_into()?, response.json().await?)),
6675            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6676        }
6677    }
6678
6679    /// Create a new git tag in a repository
6680    ///
6681    /// - `owner`: owner of the repo
6682    /// - `repo`: name of the repo
6683    /// - `body`: See [`CreateTagOption`]
6684    pub async fn repo_create_tag(
6685        &self,
6686        owner: &str,
6687        repo: &str,
6688        body: CreateTagOption,
6689    ) -> Result<Tag, ForgejoError> {
6690        let request = self
6691            .post(&format!("repos/{owner}/{repo}/tags"))
6692            .json(&body)
6693            .build()?;
6694        let response = self.execute(request).await?;
6695        match response.status().as_u16() {
6696            201 => Ok(response.json().await?),
6697            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6698        }
6699    }
6700
6701    /// Get the tag of a repository by tag name
6702    ///
6703    /// - `owner`: owner of the repo
6704    /// - `repo`: name of the repo
6705    /// - `tag`: name of tag
6706    pub async fn repo_get_tag(
6707        &self,
6708        owner: &str,
6709        repo: &str,
6710        tag: &str,
6711    ) -> Result<Tag, ForgejoError> {
6712        let request = self
6713            .get(&format!("repos/{owner}/{repo}/tags/{tag}"))
6714            .build()?;
6715        let response = self.execute(request).await?;
6716        match response.status().as_u16() {
6717            200 => Ok(response.json().await?),
6718            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6719        }
6720    }
6721
6722    /// Delete a repository's tag by name
6723    ///
6724    /// - `owner`: owner of the repo
6725    /// - `repo`: name of the repo
6726    /// - `tag`: name of tag to delete
6727    pub async fn repo_delete_tag(
6728        &self,
6729        owner: &str,
6730        repo: &str,
6731        tag: &str,
6732    ) -> Result<(), ForgejoError> {
6733        let request = self
6734            .delete(&format!("repos/{owner}/{repo}/tags/{tag}"))
6735            .build()?;
6736        let response = self.execute(request).await?;
6737        match response.status().as_u16() {
6738            204 => Ok(()),
6739            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6740        }
6741    }
6742
6743    /// List a repository's teams
6744    ///
6745    /// - `owner`: owner of the repo
6746    /// - `repo`: name of the repo
6747    pub async fn repo_list_teams(
6748        &self,
6749        owner: &str,
6750        repo: &str,
6751    ) -> Result<(TeamListHeaders, Vec<Team>), ForgejoError> {
6752        let request = self.get(&format!("repos/{owner}/{repo}/teams")).build()?;
6753        let response = self.execute(request).await?;
6754        match response.status().as_u16() {
6755            200 => Ok((response.headers().try_into()?, response.json().await?)),
6756            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6757        }
6758    }
6759
6760    /// Check if a team is assigned to a repository
6761    ///
6762    /// - `owner`: owner of the repo
6763    /// - `repo`: name of the repo
6764    /// - `team`: team name
6765    pub async fn repo_check_team(
6766        &self,
6767        owner: &str,
6768        repo: &str,
6769        team: &str,
6770    ) -> Result<Team, ForgejoError> {
6771        let request = self
6772            .get(&format!("repos/{owner}/{repo}/teams/{team}"))
6773            .build()?;
6774        let response = self.execute(request).await?;
6775        match response.status().as_u16() {
6776            200 => Ok(response.json().await?),
6777            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6778        }
6779    }
6780
6781    /// Add a team to a repository
6782    ///
6783    /// - `owner`: owner of the repo
6784    /// - `repo`: name of the repo
6785    /// - `team`: team name
6786    pub async fn repo_add_team(
6787        &self,
6788        owner: &str,
6789        repo: &str,
6790        team: &str,
6791    ) -> Result<(), ForgejoError> {
6792        let request = self
6793            .put(&format!("repos/{owner}/{repo}/teams/{team}"))
6794            .build()?;
6795        let response = self.execute(request).await?;
6796        match response.status().as_u16() {
6797            204 => Ok(()),
6798            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6799        }
6800    }
6801
6802    /// Delete a team from a repository
6803    ///
6804    /// - `owner`: owner of the repo
6805    /// - `repo`: name of the repo
6806    /// - `team`: team name
6807    pub async fn repo_delete_team(
6808        &self,
6809        owner: &str,
6810        repo: &str,
6811        team: &str,
6812    ) -> Result<(), ForgejoError> {
6813        let request = self
6814            .delete(&format!("repos/{owner}/{repo}/teams/{team}"))
6815            .build()?;
6816        let response = self.execute(request).await?;
6817        match response.status().as_u16() {
6818            204 => Ok(()),
6819            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6820        }
6821    }
6822
6823    /// List a repo's tracked times
6824    ///
6825    /// - `owner`: owner of the repo
6826    /// - `repo`: name of the repo
6827    pub async fn repo_tracked_times(
6828        &self,
6829        owner: &str,
6830        repo: &str,
6831        query: RepoTrackedTimesQuery,
6832    ) -> Result<(TrackedTimeListHeaders, Vec<TrackedTime>), ForgejoError> {
6833        let request = self
6834            .get(&format!("repos/{owner}/{repo}/times?{query}"))
6835            .build()?;
6836        let response = self.execute(request).await?;
6837        match response.status().as_u16() {
6838            200 => Ok((response.headers().try_into()?, response.json().await?)),
6839            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6840        }
6841    }
6842
6843    /// List a user's tracked times in a repo
6844    ///
6845    /// - `owner`: owner of the repo
6846    /// - `repo`: name of the repo
6847    /// - `user`: username of user
6848    pub async fn user_tracked_times(
6849        &self,
6850        owner: &str,
6851        repo: &str,
6852        user: &str,
6853    ) -> Result<(TrackedTimeListHeaders, Vec<TrackedTime>), ForgejoError> {
6854        let request = self
6855            .get(&format!("repos/{owner}/{repo}/times/{user}"))
6856            .build()?;
6857        let response = self.execute(request).await?;
6858        match response.status().as_u16() {
6859            200 => Ok((response.headers().try_into()?, response.json().await?)),
6860            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6861        }
6862    }
6863
6864    /// Get list of topics that a repository has
6865    ///
6866    /// - `owner`: owner of the repo
6867    /// - `repo`: name of the repo
6868    pub async fn repo_list_topics(
6869        &self,
6870        owner: &str,
6871        repo: &str,
6872        query: RepoListTopicsQuery,
6873    ) -> Result<TopicName, ForgejoError> {
6874        let request = self
6875            .get(&format!("repos/{owner}/{repo}/topics?{query}"))
6876            .build()?;
6877        let response = self.execute(request).await?;
6878        match response.status().as_u16() {
6879            200 => Ok(response.json().await?),
6880            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6881        }
6882    }
6883
6884    /// Replace list of topics for a repository
6885    ///
6886    /// - `owner`: owner of the repo
6887    /// - `repo`: name of the repo
6888    /// - `body`: See [`RepoTopicOptions`]
6889    pub async fn repo_update_topics(
6890        &self,
6891        owner: &str,
6892        repo: &str,
6893        body: RepoTopicOptions,
6894    ) -> Result<(), ForgejoError> {
6895        let request = self
6896            .put(&format!("repos/{owner}/{repo}/topics"))
6897            .json(&body)
6898            .build()?;
6899        let response = self.execute(request).await?;
6900        match response.status().as_u16() {
6901            204 => Ok(()),
6902            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6903        }
6904    }
6905
6906    /// Add a topic to a repository
6907    ///
6908    /// - `owner`: owner of the repo
6909    /// - `repo`: name of the repo
6910    /// - `topic`: name of the topic to add
6911    pub async fn repo_add_topic(
6912        &self,
6913        owner: &str,
6914        repo: &str,
6915        topic: &str,
6916    ) -> Result<(), ForgejoError> {
6917        let request = self
6918            .put(&format!("repos/{owner}/{repo}/topics/{topic}"))
6919            .build()?;
6920        let response = self.execute(request).await?;
6921        match response.status().as_u16() {
6922            204 => Ok(()),
6923            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6924        }
6925    }
6926
6927    /// Delete a topic from a repository
6928    ///
6929    /// - `owner`: owner of the repo
6930    /// - `repo`: name of the repo
6931    /// - `topic`: name of the topic to delete
6932    pub async fn repo_delete_topic(
6933        &self,
6934        owner: &str,
6935        repo: &str,
6936        topic: &str,
6937    ) -> Result<(), ForgejoError> {
6938        let request = self
6939            .delete(&format!("repos/{owner}/{repo}/topics/{topic}"))
6940            .build()?;
6941        let response = self.execute(request).await?;
6942        match response.status().as_u16() {
6943            204 => Ok(()),
6944            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6945        }
6946    }
6947
6948    /// Transfer a repo ownership
6949    ///
6950    /// - `owner`: owner of the repo to transfer
6951    /// - `repo`: name of the repo to transfer
6952    /// - `body`: Transfer Options
6953
6954    ///   See [`TransferRepoOption`]
6955    pub async fn repo_transfer(
6956        &self,
6957        owner: &str,
6958        repo: &str,
6959        body: TransferRepoOption,
6960    ) -> Result<Repository, ForgejoError> {
6961        let request = self
6962            .post(&format!("repos/{owner}/{repo}/transfer"))
6963            .json(&body)
6964            .build()?;
6965        let response = self.execute(request).await?;
6966        match response.status().as_u16() {
6967            202 => Ok(response.json().await?),
6968            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6969        }
6970    }
6971
6972    /// Accept a repo transfer
6973    ///
6974    /// - `owner`: owner of the repo to transfer
6975    /// - `repo`: name of the repo to transfer
6976    pub async fn accept_repo_transfer(
6977        &self,
6978        owner: &str,
6979        repo: &str,
6980    ) -> Result<Repository, ForgejoError> {
6981        let request = self
6982            .post(&format!("repos/{owner}/{repo}/transfer/accept"))
6983            .build()?;
6984        let response = self.execute(request).await?;
6985        match response.status().as_u16() {
6986            202 => Ok(response.json().await?),
6987            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
6988        }
6989    }
6990
6991    /// Reject a repo transfer
6992    ///
6993    /// - `owner`: owner of the repo to transfer
6994    /// - `repo`: name of the repo to transfer
6995    pub async fn reject_repo_transfer(
6996        &self,
6997        owner: &str,
6998        repo: &str,
6999    ) -> Result<Repository, ForgejoError> {
7000        let request = self
7001            .post(&format!("repos/{owner}/{repo}/transfer/reject"))
7002            .build()?;
7003        let response = self.execute(request).await?;
7004        match response.status().as_u16() {
7005            200 => Ok(response.json().await?),
7006            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7007        }
7008    }
7009
7010    /// Create a wiki page
7011    ///
7012    /// - `owner`: owner of the repo
7013    /// - `repo`: name of the repo
7014    /// - `body`: See [`CreateWikiPageOptions`]
7015    pub async fn repo_create_wiki_page(
7016        &self,
7017        owner: &str,
7018        repo: &str,
7019        body: CreateWikiPageOptions,
7020    ) -> Result<WikiPage, ForgejoError> {
7021        let request = self
7022            .post(&format!("repos/{owner}/{repo}/wiki/new"))
7023            .json(&body)
7024            .build()?;
7025        let response = self.execute(request).await?;
7026        match response.status().as_u16() {
7027            201 => Ok(response.json().await?),
7028            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7029        }
7030    }
7031
7032    /// Get a wiki page
7033    ///
7034    /// - `owner`: owner of the repo
7035    /// - `repo`: name of the repo
7036    /// - `pageName`: name of the page
7037    pub async fn repo_get_wiki_page(
7038        &self,
7039        owner: &str,
7040        repo: &str,
7041        page_name: &str,
7042    ) -> Result<WikiPage, ForgejoError> {
7043        let request = self
7044            .get(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
7045            .build()?;
7046        let response = self.execute(request).await?;
7047        match response.status().as_u16() {
7048            200 => Ok(response.json().await?),
7049            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7050        }
7051    }
7052
7053    /// Delete a wiki page
7054    ///
7055    /// - `owner`: owner of the repo
7056    /// - `repo`: name of the repo
7057    /// - `pageName`: name of the page
7058    pub async fn repo_delete_wiki_page(
7059        &self,
7060        owner: &str,
7061        repo: &str,
7062        page_name: &str,
7063    ) -> Result<(), ForgejoError> {
7064        let request = self
7065            .delete(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
7066            .build()?;
7067        let response = self.execute(request).await?;
7068        match response.status().as_u16() {
7069            204 => Ok(()),
7070            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7071        }
7072    }
7073
7074    /// Edit a wiki page
7075    ///
7076    /// - `owner`: owner of the repo
7077    /// - `repo`: name of the repo
7078    /// - `pageName`: name of the page
7079    /// - `body`: See [`CreateWikiPageOptions`]
7080    pub async fn repo_edit_wiki_page(
7081        &self,
7082        owner: &str,
7083        repo: &str,
7084        page_name: &str,
7085        body: CreateWikiPageOptions,
7086    ) -> Result<WikiPage, ForgejoError> {
7087        let request = self
7088            .patch(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
7089            .json(&body)
7090            .build()?;
7091        let response = self.execute(request).await?;
7092        match response.status().as_u16() {
7093            200 => Ok(response.json().await?),
7094            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7095        }
7096    }
7097
7098    /// Get all wiki pages
7099    ///
7100    /// - `owner`: owner of the repo
7101    /// - `repo`: name of the repo
7102    pub async fn repo_get_wiki_pages(
7103        &self,
7104        owner: &str,
7105        repo: &str,
7106        query: RepoGetWikiPagesQuery,
7107    ) -> Result<(WikiPageListHeaders, Vec<WikiPageMetaData>), ForgejoError> {
7108        let request = self
7109            .get(&format!("repos/{owner}/{repo}/wiki/pages?{query}"))
7110            .build()?;
7111        let response = self.execute(request).await?;
7112        match response.status().as_u16() {
7113            200 => Ok((response.headers().try_into()?, response.json().await?)),
7114            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7115        }
7116    }
7117
7118    /// Get revisions of a wiki page
7119    ///
7120    /// - `owner`: owner of the repo
7121    /// - `repo`: name of the repo
7122    /// - `pageName`: name of the page
7123    pub async fn repo_get_wiki_page_revisions(
7124        &self,
7125        owner: &str,
7126        repo: &str,
7127        page_name: &str,
7128        query: RepoGetWikiPageRevisionsQuery,
7129    ) -> Result<(WikiCommitListHeaders, WikiCommitList), ForgejoError> {
7130        let request = self
7131            .get(&format!(
7132                "repos/{owner}/{repo}/wiki/revisions/{page_name}?{query}"
7133            ))
7134            .build()?;
7135        let response = self.execute(request).await?;
7136        match response.status().as_u16() {
7137            200 => Ok((response.headers().try_into()?, response.json().await?)),
7138            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7139        }
7140    }
7141
7142    /// Create a repository using a template
7143    ///
7144    /// - `template_owner`: name of the template repository owner
7145    /// - `template_repo`: name of the template repository
7146    /// - `body`: See [`GenerateRepoOption`]
7147    pub async fn generate_repo(
7148        &self,
7149        template_owner: &str,
7150        template_repo: &str,
7151        body: GenerateRepoOption,
7152    ) -> Result<Repository, ForgejoError> {
7153        let request = self
7154            .post(&format!("repos/{template_owner}/{template_repo}/generate"))
7155            .json(&body)
7156            .build()?;
7157        let response = self.execute(request).await?;
7158        match response.status().as_u16() {
7159            201 => Ok(response.json().await?),
7160            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7161        }
7162    }
7163
7164    /// Get a repository by id
7165    ///
7166    /// - `id`: id of the repo to get
7167    pub async fn repo_get_by_id(&self, id: u64) -> Result<Repository, ForgejoError> {
7168        let request = self.get(&format!("repositories/{id}")).build()?;
7169        let response = self.execute(request).await?;
7170        match response.status().as_u16() {
7171            200 => Ok(response.json().await?),
7172            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7173        }
7174    }
7175
7176    /// Get instance's global settings for api
7177    pub async fn get_general_api_settings(&self) -> Result<GeneralAPISettings, ForgejoError> {
7178        let request = self.get("settings/api").build()?;
7179        let response = self.execute(request).await?;
7180        match response.status().as_u16() {
7181            200 => Ok(response.json().await?),
7182            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7183        }
7184    }
7185
7186    /// Get instance's global settings for Attachment
7187    pub async fn get_general_attachment_settings(
7188        &self,
7189    ) -> Result<GeneralAttachmentSettings, ForgejoError> {
7190        let request = self.get("settings/attachment").build()?;
7191        let response = self.execute(request).await?;
7192        match response.status().as_u16() {
7193            200 => Ok(response.json().await?),
7194            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7195        }
7196    }
7197
7198    /// Get instance's global settings for repositories
7199    pub async fn get_general_repository_settings(
7200        &self,
7201    ) -> Result<GeneralRepoSettings, ForgejoError> {
7202        let request = self.get("settings/repository").build()?;
7203        let response = self.execute(request).await?;
7204        match response.status().as_u16() {
7205            200 => Ok(response.json().await?),
7206            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7207        }
7208    }
7209
7210    /// Get instance's global settings for ui
7211    pub async fn get_general_ui_settings(&self) -> Result<GeneralUISettings, ForgejoError> {
7212        let request = self.get("settings/ui").build()?;
7213        let response = self.execute(request).await?;
7214        match response.status().as_u16() {
7215            200 => Ok(response.json().await?),
7216            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7217        }
7218    }
7219
7220    /// Get default signing-key.gpg
7221    pub async fn get_signing_key(&self) -> Result<String, ForgejoError> {
7222        let request = self.get("signing-key.gpg").build()?;
7223        let response = self.execute(request).await?;
7224        match response.status().as_u16() {
7225            200 => Ok(response.text().await?),
7226            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7227        }
7228    }
7229
7230    /// Get a team
7231    ///
7232    /// - `id`: id of the team to get
7233    pub async fn org_get_team(&self, id: u64) -> Result<Team, ForgejoError> {
7234        let request = self.get(&format!("teams/{id}")).build()?;
7235        let response = self.execute(request).await?;
7236        match response.status().as_u16() {
7237            200 => Ok(response.json().await?),
7238            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7239        }
7240    }
7241
7242    /// Delete a team
7243    ///
7244    /// - `id`: id of the team to delete
7245    pub async fn org_delete_team(&self, id: u64) -> Result<(), ForgejoError> {
7246        let request = self.delete(&format!("teams/{id}")).build()?;
7247        let response = self.execute(request).await?;
7248        match response.status().as_u16() {
7249            204 => Ok(()),
7250            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7251        }
7252    }
7253
7254    /// Edit a team
7255    ///
7256    /// - `id`: id of the team to edit
7257    /// - `body`: See [`EditTeamOption`]
7258    pub async fn org_edit_team(&self, id: u32, body: EditTeamOption) -> Result<Team, ForgejoError> {
7259        let request = self.patch(&format!("teams/{id}")).json(&body).build()?;
7260        let response = self.execute(request).await?;
7261        match response.status().as_u16() {
7262            200 => Ok(response.json().await?),
7263            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7264        }
7265    }
7266
7267    /// List a team's activity feeds
7268    ///
7269    /// - `id`: id of the team
7270    pub async fn org_list_team_activity_feeds(
7271        &self,
7272        id: u64,
7273        query: OrgListTeamActivityFeedsQuery,
7274    ) -> Result<(ActivityFeedsListHeaders, Vec<Activity>), ForgejoError> {
7275        let request = self
7276            .get(&format!("teams/{id}/activities/feeds?{query}"))
7277            .build()?;
7278        let response = self.execute(request).await?;
7279        match response.status().as_u16() {
7280            200 => Ok((response.headers().try_into()?, response.json().await?)),
7281            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7282        }
7283    }
7284
7285    /// List a team's members
7286    ///
7287    /// - `id`: id of the team
7288    pub async fn org_list_team_members(
7289        &self,
7290        id: u64,
7291        query: OrgListTeamMembersQuery,
7292    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
7293        let request = self.get(&format!("teams/{id}/members?{query}")).build()?;
7294        let response = self.execute(request).await?;
7295        match response.status().as_u16() {
7296            200 => Ok((response.headers().try_into()?, response.json().await?)),
7297            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7298        }
7299    }
7300
7301    /// List a particular member of team
7302    ///
7303    /// - `id`: id of the team
7304    /// - `username`: username of the member to list
7305    pub async fn org_list_team_member(
7306        &self,
7307        id: u64,
7308        username: &str,
7309    ) -> Result<User, ForgejoError> {
7310        let request = self
7311            .get(&format!("teams/{id}/members/{username}"))
7312            .build()?;
7313        let response = self.execute(request).await?;
7314        match response.status().as_u16() {
7315            200 => Ok(response.json().await?),
7316            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7317        }
7318    }
7319
7320    /// Add a team member
7321    ///
7322    /// - `id`: id of the team
7323    /// - `username`: username of the user to add
7324    pub async fn org_add_team_member(&self, id: u64, username: &str) -> Result<(), ForgejoError> {
7325        let request = self
7326            .put(&format!("teams/{id}/members/{username}"))
7327            .build()?;
7328        let response = self.execute(request).await?;
7329        match response.status().as_u16() {
7330            204 => Ok(()),
7331            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7332        }
7333    }
7334
7335    /// Remove a team member
7336    ///
7337    /// - `id`: id of the team
7338    /// - `username`: username of the user to remove
7339    pub async fn org_remove_team_member(
7340        &self,
7341        id: u64,
7342        username: &str,
7343    ) -> Result<(), ForgejoError> {
7344        let request = self
7345            .delete(&format!("teams/{id}/members/{username}"))
7346            .build()?;
7347        let response = self.execute(request).await?;
7348        match response.status().as_u16() {
7349            204 => Ok(()),
7350            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7351        }
7352    }
7353
7354    /// List a team's repos
7355    ///
7356    /// - `id`: id of the team
7357    pub async fn org_list_team_repos(
7358        &self,
7359        id: u64,
7360        query: OrgListTeamReposQuery,
7361    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
7362        let request = self.get(&format!("teams/{id}/repos?{query}")).build()?;
7363        let response = self.execute(request).await?;
7364        match response.status().as_u16() {
7365            200 => Ok((response.headers().try_into()?, response.json().await?)),
7366            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7367        }
7368    }
7369
7370    /// List a particular repo of team
7371    ///
7372    /// - `id`: id of the team
7373    /// - `org`: organization that owns the repo to list
7374    /// - `repo`: name of the repo to list
7375    pub async fn org_list_team_repo(
7376        &self,
7377        id: u64,
7378        org: &str,
7379        repo: &str,
7380    ) -> Result<Repository, ForgejoError> {
7381        let request = self
7382            .get(&format!("teams/{id}/repos/{org}/{repo}"))
7383            .build()?;
7384        let response = self.execute(request).await?;
7385        match response.status().as_u16() {
7386            200 => Ok(response.json().await?),
7387            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7388        }
7389    }
7390
7391    /// Add a repository to a team
7392    ///
7393    /// - `id`: id of the team
7394    /// - `org`: organization that owns the repo to add
7395    /// - `repo`: name of the repo to add
7396    pub async fn org_add_team_repository(
7397        &self,
7398        id: u64,
7399        org: &str,
7400        repo: &str,
7401    ) -> Result<(), ForgejoError> {
7402        let request = self
7403            .put(&format!("teams/{id}/repos/{org}/{repo}"))
7404            .build()?;
7405        let response = self.execute(request).await?;
7406        match response.status().as_u16() {
7407            204 => Ok(()),
7408            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7409        }
7410    }
7411
7412    /// Remove a repository from a team
7413    ///
7414    /// - `id`: id of the team
7415    /// - `org`: organization that owns the repo to remove
7416    /// - `repo`: name of the repo to remove
7417    pub async fn org_remove_team_repository(
7418        &self,
7419        id: u64,
7420        org: &str,
7421        repo: &str,
7422    ) -> Result<(), ForgejoError> {
7423        let request = self
7424            .delete(&format!("teams/{id}/repos/{org}/{repo}"))
7425            .build()?;
7426        let response = self.execute(request).await?;
7427        match response.status().as_u16() {
7428            204 => Ok(()),
7429            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7430        }
7431    }
7432
7433    /// search topics via keyword
7434    ///
7435    pub async fn topic_search(
7436        &self,
7437        query: TopicSearchQuery,
7438    ) -> Result<Vec<TopicResponse>, ForgejoError> {
7439        let request = self.get(&format!("topics/search?{query}")).build()?;
7440        let response = self.execute(request).await?;
7441        match response.status().as_u16() {
7442            200 => Ok(response.json().await?),
7443            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7444        }
7445    }
7446
7447    /// Get the authenticated user
7448    pub async fn user_get_current(&self) -> Result<User, ForgejoError> {
7449        let request = self.get("user").build()?;
7450        let response = self.execute(request).await?;
7451        match response.status().as_u16() {
7452            200 => Ok(response.json().await?),
7453            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7454        }
7455    }
7456
7457    /// Get an user's actions runner registration token
7458    pub async fn user_get_runner_registration_token(
7459        &self,
7460    ) -> Result<RegistrationTokenHeaders, ForgejoError> {
7461        let request = self
7462            .get("user/actions/runners/registration-token")
7463            .build()?;
7464        let response = self.execute(request).await?;
7465        match response.status().as_u16() {
7466            200 => Ok(response.headers().try_into()?),
7467            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7468        }
7469    }
7470
7471    /// Create or Update a secret value in a user scope
7472    ///
7473    /// - `secretname`: name of the secret
7474    /// - `body`: See [`CreateOrUpdateSecretOption`]
7475    pub async fn update_user_secret(
7476        &self,
7477        secretname: &str,
7478        body: CreateOrUpdateSecretOption,
7479    ) -> Result<(), ForgejoError> {
7480        let request = self
7481            .put(&format!("user/actions/secrets/{secretname}"))
7482            .json(&body)
7483            .build()?;
7484        let response = self.execute(request).await?;
7485        match response.status().as_u16() {
7486            201 => Ok(()),
7487            204 => Ok(()),
7488            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7489        }
7490    }
7491
7492    /// Delete a secret in a user scope
7493    ///
7494    /// - `secretname`: name of the secret
7495    pub async fn delete_user_secret(&self, secretname: &str) -> Result<(), ForgejoError> {
7496        let request = self
7497            .delete(&format!("user/actions/secrets/{secretname}"))
7498            .build()?;
7499        let response = self.execute(request).await?;
7500        match response.status().as_u16() {
7501            204 => Ok(()),
7502            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7503        }
7504    }
7505
7506    /// Get the user-level list of variables which is created by current doer
7507    ///
7508    pub async fn get_user_variables_list(
7509        &self,
7510        query: GetUserVariablesListQuery,
7511    ) -> Result<(VariableListHeaders, Vec<ActionVariable>), ForgejoError> {
7512        let request = self
7513            .get(&format!("user/actions/variables?{query}"))
7514            .build()?;
7515        let response = self.execute(request).await?;
7516        match response.status().as_u16() {
7517            200 => Ok((response.headers().try_into()?, response.json().await?)),
7518            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7519        }
7520    }
7521
7522    /// Get a user-level variable which is created by current doer
7523    ///
7524    /// - `variablename`: name of the variable
7525    pub async fn get_user_variable(
7526        &self,
7527        variablename: &str,
7528    ) -> Result<ActionVariable, ForgejoError> {
7529        let request = self
7530            .get(&format!("user/actions/variables/{variablename}"))
7531            .build()?;
7532        let response = self.execute(request).await?;
7533        match response.status().as_u16() {
7534            200 => Ok(response.json().await?),
7535            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7536        }
7537    }
7538
7539    /// Update a user-level variable which is created by current doer
7540    ///
7541    /// - `variablename`: name of the variable
7542    /// - `body`: See [`UpdateVariableOption`]
7543    pub async fn update_user_variable(
7544        &self,
7545        variablename: &str,
7546        body: UpdateVariableOption,
7547    ) -> Result<(), ForgejoError> {
7548        let request = self
7549            .put(&format!("user/actions/variables/{variablename}"))
7550            .json(&body)
7551            .build()?;
7552        let response = self.execute(request).await?;
7553        match response.status().as_u16() {
7554            201 => Ok(()),
7555            204 => Ok(()),
7556            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7557        }
7558    }
7559
7560    /// Create a user-level variable
7561    ///
7562    /// - `variablename`: name of the variable
7563    /// - `body`: See [`CreateVariableOption`]
7564    pub async fn create_user_variable(
7565        &self,
7566        variablename: &str,
7567        body: CreateVariableOption,
7568    ) -> Result<(), ForgejoError> {
7569        let request = self
7570            .post(&format!("user/actions/variables/{variablename}"))
7571            .json(&body)
7572            .build()?;
7573        let response = self.execute(request).await?;
7574        match response.status().as_u16() {
7575            201 => Ok(()),
7576            204 => Ok(()),
7577            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7578        }
7579    }
7580
7581    /// Delete a user-level variable which is created by current doer
7582    ///
7583    /// - `variablename`: name of the variable
7584    pub async fn delete_user_variable(&self, variablename: &str) -> Result<(), ForgejoError> {
7585        let request = self
7586            .delete(&format!("user/actions/variables/{variablename}"))
7587            .build()?;
7588        let response = self.execute(request).await?;
7589        match response.status().as_u16() {
7590            201 => Ok(()),
7591            204 => Ok(()),
7592            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7593        }
7594    }
7595
7596    /// List the authenticated user's oauth2 applications
7597    ///
7598    pub async fn user_get_oauth2_applications(
7599        &self,
7600        query: UserGetOAuth2ApplicationsQuery,
7601    ) -> Result<(OAuth2ApplicationListHeaders, Vec<OAuth2Application>), ForgejoError> {
7602        let request = self
7603            .get(&format!("user/applications/oauth2?{query}"))
7604            .build()?;
7605        let response = self.execute(request).await?;
7606        match response.status().as_u16() {
7607            200 => Ok((response.headers().try_into()?, response.json().await?)),
7608            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7609        }
7610    }
7611
7612    /// creates a new OAuth2 application
7613    ///
7614    /// - `body`: See [`CreateOAuth2ApplicationOptions`]
7615    pub async fn user_create_oauth2_application(
7616        &self,
7617        body: CreateOAuth2ApplicationOptions,
7618    ) -> Result<OAuth2Application, ForgejoError> {
7619        let request = self.post("user/applications/oauth2").json(&body).build()?;
7620        let response = self.execute(request).await?;
7621        match response.status().as_u16() {
7622            201 => Ok(response.json().await?),
7623            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7624        }
7625    }
7626
7627    /// get an OAuth2 Application
7628    ///
7629    /// - `id`: Application ID to be found
7630    pub async fn user_get_oauth2_application(
7631        &self,
7632        id: u64,
7633    ) -> Result<OAuth2Application, ForgejoError> {
7634        let request = self
7635            .get(&format!("user/applications/oauth2/{id}"))
7636            .build()?;
7637        let response = self.execute(request).await?;
7638        match response.status().as_u16() {
7639            200 => Ok(response.json().await?),
7640            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7641        }
7642    }
7643
7644    /// delete an OAuth2 Application
7645    ///
7646    /// - `id`: token to be deleted
7647    pub async fn user_delete_oauth2_application(&self, id: u64) -> Result<(), ForgejoError> {
7648        let request = self
7649            .delete(&format!("user/applications/oauth2/{id}"))
7650            .build()?;
7651        let response = self.execute(request).await?;
7652        match response.status().as_u16() {
7653            204 => Ok(()),
7654            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7655        }
7656    }
7657
7658    /// update an OAuth2 Application, this includes regenerating the client secret
7659    ///
7660    /// - `id`: application to be updated
7661    /// - `body`: See [`CreateOAuth2ApplicationOptions`]
7662    pub async fn user_update_oauth2_application(
7663        &self,
7664        id: u64,
7665        body: CreateOAuth2ApplicationOptions,
7666    ) -> Result<OAuth2Application, ForgejoError> {
7667        let request = self
7668            .patch(&format!("user/applications/oauth2/{id}"))
7669            .json(&body)
7670            .build()?;
7671        let response = self.execute(request).await?;
7672        match response.status().as_u16() {
7673            200 => Ok(response.json().await?),
7674            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7675        }
7676    }
7677
7678    /// Update Avatar
7679    ///
7680    /// - `body`: See [`UpdateUserAvatarOption`]
7681    pub async fn user_update_avatar(
7682        &self,
7683        body: UpdateUserAvatarOption,
7684    ) -> Result<(), ForgejoError> {
7685        let request = self.post("user/avatar").json(&body).build()?;
7686        let response = self.execute(request).await?;
7687        match response.status().as_u16() {
7688            204 => Ok(()),
7689            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7690        }
7691    }
7692
7693    /// Delete Avatar
7694    pub async fn user_delete_avatar(&self) -> Result<(), ForgejoError> {
7695        let request = self.delete("user/avatar").build()?;
7696        let response = self.execute(request).await?;
7697        match response.status().as_u16() {
7698            204 => Ok(()),
7699            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7700        }
7701    }
7702
7703    /// Blocks a user from the doer.
7704    ///
7705    /// - `username`: username of the user
7706    pub async fn user_block_user(&self, username: &str) -> Result<(), ForgejoError> {
7707        let request = self.put(&format!("user/block/{username}")).build()?;
7708        let response = self.execute(request).await?;
7709        match response.status().as_u16() {
7710            204 => Ok(()),
7711            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7712        }
7713    }
7714
7715    /// List the authenticated user's email addresses
7716    pub async fn user_list_emails(&self) -> Result<Vec<Email>, ForgejoError> {
7717        let request = self.get("user/emails").build()?;
7718        let response = self.execute(request).await?;
7719        match response.status().as_u16() {
7720            200 => Ok(response.json().await?),
7721            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7722        }
7723    }
7724
7725    /// Add email addresses
7726    ///
7727    /// - `body`: See [`CreateEmailOption`]
7728    pub async fn user_add_email(
7729        &self,
7730        body: CreateEmailOption,
7731    ) -> Result<Vec<Email>, ForgejoError> {
7732        let request = self.post("user/emails").json(&body).build()?;
7733        let response = self.execute(request).await?;
7734        match response.status().as_u16() {
7735            201 => Ok(response.json().await?),
7736            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7737        }
7738    }
7739
7740    /// Delete email addresses
7741    ///
7742    /// - `body`: See [`DeleteEmailOption`]
7743    pub async fn user_delete_email(&self, body: DeleteEmailOption) -> Result<(), ForgejoError> {
7744        let request = self.delete("user/emails").json(&body).build()?;
7745        let response = self.execute(request).await?;
7746        match response.status().as_u16() {
7747            204 => Ok(()),
7748            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7749        }
7750    }
7751
7752    /// List the authenticated user's followers
7753    ///
7754    pub async fn user_current_list_followers(
7755        &self,
7756        query: UserCurrentListFollowersQuery,
7757    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
7758        let request = self.get(&format!("user/followers?{query}")).build()?;
7759        let response = self.execute(request).await?;
7760        match response.status().as_u16() {
7761            200 => Ok((response.headers().try_into()?, response.json().await?)),
7762            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7763        }
7764    }
7765
7766    /// List the users that the authenticated user is following
7767    ///
7768    pub async fn user_current_list_following(
7769        &self,
7770        query: UserCurrentListFollowingQuery,
7771    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
7772        let request = self.get(&format!("user/following?{query}")).build()?;
7773        let response = self.execute(request).await?;
7774        match response.status().as_u16() {
7775            200 => Ok((response.headers().try_into()?, response.json().await?)),
7776            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7777        }
7778    }
7779
7780    /// Check whether a user is followed by the authenticated user
7781    ///
7782    /// - `username`: username of followed user
7783    pub async fn user_current_check_following(&self, username: &str) -> Result<(), ForgejoError> {
7784        let request = self.get(&format!("user/following/{username}")).build()?;
7785        let response = self.execute(request).await?;
7786        match response.status().as_u16() {
7787            204 => Ok(()),
7788            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7789        }
7790    }
7791
7792    /// Follow a user
7793    ///
7794    /// - `username`: username of user to follow
7795    pub async fn user_current_put_follow(&self, username: &str) -> Result<(), ForgejoError> {
7796        let request = self.put(&format!("user/following/{username}")).build()?;
7797        let response = self.execute(request).await?;
7798        match response.status().as_u16() {
7799            204 => Ok(()),
7800            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7801        }
7802    }
7803
7804    /// Unfollow a user
7805    ///
7806    /// - `username`: username of user to unfollow
7807    pub async fn user_current_delete_follow(&self, username: &str) -> Result<(), ForgejoError> {
7808        let request = self.delete(&format!("user/following/{username}")).build()?;
7809        let response = self.execute(request).await?;
7810        match response.status().as_u16() {
7811            204 => Ok(()),
7812            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7813        }
7814    }
7815
7816    /// Get a Token to verify
7817    pub async fn get_verification_token(&self) -> Result<String, ForgejoError> {
7818        let request = self.get("user/gpg_key_token").build()?;
7819        let response = self.execute(request).await?;
7820        match response.status().as_u16() {
7821            200 => Ok(response.text().await?),
7822            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7823        }
7824    }
7825
7826    /// Verify a GPG key
7827    pub async fn user_verify_gpg_key(&self) -> Result<GPGKey, ForgejoError> {
7828        let request = self.post("user/gpg_key_verify").build()?;
7829        let response = self.execute(request).await?;
7830        match response.status().as_u16() {
7831            201 => Ok(response.json().await?),
7832            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7833        }
7834    }
7835
7836    /// List the authenticated user's GPG keys
7837    ///
7838    pub async fn user_current_list_gpg_keys(
7839        &self,
7840        query: UserCurrentListGpgKeysQuery,
7841    ) -> Result<(GpgKeyListHeaders, Vec<GPGKey>), ForgejoError> {
7842        let request = self.get(&format!("user/gpg_keys?{query}")).build()?;
7843        let response = self.execute(request).await?;
7844        match response.status().as_u16() {
7845            200 => Ok((response.headers().try_into()?, response.json().await?)),
7846            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7847        }
7848    }
7849
7850    /// Create a GPG key
7851    ///
7852    /// - `Form`: See [`CreateGPGKeyOption`]
7853    pub async fn user_current_post_gpg_key(
7854        &self,
7855        form: CreateGPGKeyOption,
7856    ) -> Result<GPGKey, ForgejoError> {
7857        let request = self.post("user/gpg_keys").json(&form).build()?;
7858        let response = self.execute(request).await?;
7859        match response.status().as_u16() {
7860            201 => Ok(response.json().await?),
7861            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7862        }
7863    }
7864
7865    /// Get a GPG key
7866    ///
7867    /// - `id`: id of key to get
7868    pub async fn user_current_get_gpg_key(&self, id: u64) -> Result<GPGKey, ForgejoError> {
7869        let request = self.get(&format!("user/gpg_keys/{id}")).build()?;
7870        let response = self.execute(request).await?;
7871        match response.status().as_u16() {
7872            200 => Ok(response.json().await?),
7873            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7874        }
7875    }
7876
7877    /// Remove a GPG key
7878    ///
7879    /// - `id`: id of key to delete
7880    pub async fn user_current_delete_gpg_key(&self, id: u64) -> Result<(), ForgejoError> {
7881        let request = self.delete(&format!("user/gpg_keys/{id}")).build()?;
7882        let response = self.execute(request).await?;
7883        match response.status().as_u16() {
7884            204 => Ok(()),
7885            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7886        }
7887    }
7888
7889    /// List the authenticated user's webhooks
7890    ///
7891    pub async fn user_list_hooks(
7892        &self,
7893        query: UserListHooksQuery,
7894    ) -> Result<(HookListHeaders, Vec<Hook>), ForgejoError> {
7895        let request = self.get(&format!("user/hooks?{query}")).build()?;
7896        let response = self.execute(request).await?;
7897        match response.status().as_u16() {
7898            200 => Ok((response.headers().try_into()?, response.json().await?)),
7899            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7900        }
7901    }
7902
7903    /// Create a hook
7904    ///
7905    /// - `body`: See [`CreateHookOption`]
7906    pub async fn user_create_hook(&self, body: CreateHookOption) -> Result<Hook, ForgejoError> {
7907        let request = self.post("user/hooks").json(&body).build()?;
7908        let response = self.execute(request).await?;
7909        match response.status().as_u16() {
7910            201 => Ok(response.json().await?),
7911            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7912        }
7913    }
7914
7915    /// Get a hook
7916    ///
7917    /// - `id`: id of the hook to get
7918    pub async fn user_get_hook(&self, id: u64) -> Result<Hook, ForgejoError> {
7919        let request = self.get(&format!("user/hooks/{id}")).build()?;
7920        let response = self.execute(request).await?;
7921        match response.status().as_u16() {
7922            200 => Ok(response.json().await?),
7923            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7924        }
7925    }
7926
7927    /// Delete a hook
7928    ///
7929    /// - `id`: id of the hook to delete
7930    pub async fn user_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
7931        let request = self.delete(&format!("user/hooks/{id}")).build()?;
7932        let response = self.execute(request).await?;
7933        match response.status().as_u16() {
7934            204 => Ok(()),
7935            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7936        }
7937    }
7938
7939    /// Update a hook
7940    ///
7941    /// - `id`: id of the hook to update
7942    /// - `body`: See [`EditHookOption`]
7943    pub async fn user_edit_hook(
7944        &self,
7945        id: u64,
7946        body: EditHookOption,
7947    ) -> Result<Hook, ForgejoError> {
7948        let request = self
7949            .patch(&format!("user/hooks/{id}"))
7950            .json(&body)
7951            .build()?;
7952        let response = self.execute(request).await?;
7953        match response.status().as_u16() {
7954            200 => Ok(response.json().await?),
7955            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7956        }
7957    }
7958
7959    /// List the authenticated user's public keys
7960    ///
7961    pub async fn user_current_list_keys(
7962        &self,
7963        query: UserCurrentListKeysQuery,
7964    ) -> Result<(PublicKeyListHeaders, Vec<PublicKey>), ForgejoError> {
7965        let request = self.get(&format!("user/keys?{query}")).build()?;
7966        let response = self.execute(request).await?;
7967        match response.status().as_u16() {
7968            200 => Ok((response.headers().try_into()?, response.json().await?)),
7969            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7970        }
7971    }
7972
7973    /// Create a public key
7974    ///
7975    /// - `body`: See [`CreateKeyOption`]
7976    pub async fn user_current_post_key(
7977        &self,
7978        body: CreateKeyOption,
7979    ) -> Result<PublicKey, ForgejoError> {
7980        let request = self.post("user/keys").json(&body).build()?;
7981        let response = self.execute(request).await?;
7982        match response.status().as_u16() {
7983            201 => Ok(response.json().await?),
7984            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7985        }
7986    }
7987
7988    /// Get a public key
7989    ///
7990    /// - `id`: id of key to get
7991    pub async fn user_current_get_key(&self, id: u64) -> Result<PublicKey, ForgejoError> {
7992        let request = self.get(&format!("user/keys/{id}")).build()?;
7993        let response = self.execute(request).await?;
7994        match response.status().as_u16() {
7995            200 => Ok(response.json().await?),
7996            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
7997        }
7998    }
7999
8000    /// Delete a public key
8001    ///
8002    /// - `id`: id of key to delete
8003    pub async fn user_current_delete_key(&self, id: u64) -> Result<(), ForgejoError> {
8004        let request = self.delete(&format!("user/keys/{id}")).build()?;
8005        let response = self.execute(request).await?;
8006        match response.status().as_u16() {
8007            204 => Ok(()),
8008            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8009        }
8010    }
8011
8012    /// List the authenticated user's blocked users
8013    ///
8014    pub async fn user_list_blocked_users(
8015        &self,
8016        query: UserListBlockedUsersQuery,
8017    ) -> Result<(BlockedUserListHeaders, Vec<BlockedUser>), ForgejoError> {
8018        let request = self.get(&format!("user/list_blocked?{query}")).build()?;
8019        let response = self.execute(request).await?;
8020        match response.status().as_u16() {
8021            200 => Ok((response.headers().try_into()?, response.json().await?)),
8022            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8023        }
8024    }
8025
8026    /// List the current user's organizations
8027    ///
8028    pub async fn org_list_current_user_orgs(
8029        &self,
8030        query: OrgListCurrentUserOrgsQuery,
8031    ) -> Result<(OrganizationListHeaders, Vec<Organization>), ForgejoError> {
8032        let request = self.get(&format!("user/orgs?{query}")).build()?;
8033        let response = self.execute(request).await?;
8034        match response.status().as_u16() {
8035            200 => Ok((response.headers().try_into()?, response.json().await?)),
8036            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8037        }
8038    }
8039
8040    /// Get quota information for the authenticated user
8041    pub async fn user_get_quota(&self) -> Result<QuotaInfo, ForgejoError> {
8042        let request = self.get("user/quota").build()?;
8043        let response = self.execute(request).await?;
8044        match response.status().as_u16() {
8045            200 => Ok(response.json().await?),
8046            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8047        }
8048    }
8049
8050    /// List the artifacts affecting the authenticated user's quota
8051    ///
8052    pub async fn user_list_quota_artifacts(
8053        &self,
8054        query: UserListQuotaArtifactsQuery,
8055    ) -> Result<(QuotaUsedArtifactListHeaders, Vec<QuotaUsedArtifact>), ForgejoError> {
8056        let request = self.get(&format!("user/quota/artifacts?{query}")).build()?;
8057        let response = self.execute(request).await?;
8058        match response.status().as_u16() {
8059            200 => Ok((response.headers().try_into()?, response.json().await?)),
8060            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8061        }
8062    }
8063
8064    /// List the attachments affecting the authenticated user's quota
8065    ///
8066    pub async fn user_list_quota_attachments(
8067        &self,
8068        query: UserListQuotaAttachmentsQuery,
8069    ) -> Result<(QuotaUsedAttachmentListHeaders, Vec<QuotaUsedAttachment>), ForgejoError> {
8070        let request = self
8071            .get(&format!("user/quota/attachments?{query}"))
8072            .build()?;
8073        let response = self.execute(request).await?;
8074        match response.status().as_u16() {
8075            200 => Ok((response.headers().try_into()?, response.json().await?)),
8076            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8077        }
8078    }
8079
8080    /// Check if the authenticated user is over quota for a given subject
8081    pub async fn user_check_quota(&self) -> Result<(), ForgejoError> {
8082        let request = self.get("user/quota/check").build()?;
8083        let response = self.execute(request).await?;
8084        match response.status().as_u16() {
8085            200 => Ok(()),
8086            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8087        }
8088    }
8089
8090    /// List the packages affecting the authenticated user's quota
8091    ///
8092    pub async fn user_list_quota_packages(
8093        &self,
8094        query: UserListQuotaPackagesQuery,
8095    ) -> Result<(QuotaUsedPackageListHeaders, Vec<QuotaUsedPackage>), ForgejoError> {
8096        let request = self.get(&format!("user/quota/packages?{query}")).build()?;
8097        let response = self.execute(request).await?;
8098        match response.status().as_u16() {
8099            200 => Ok((response.headers().try_into()?, response.json().await?)),
8100            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8101        }
8102    }
8103
8104    /// List the repos that the authenticated user owns
8105    ///
8106    pub async fn user_current_list_repos(
8107        &self,
8108        query: UserCurrentListReposQuery,
8109    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8110        let request = self.get(&format!("user/repos?{query}")).build()?;
8111        let response = self.execute(request).await?;
8112        match response.status().as_u16() {
8113            200 => Ok((response.headers().try_into()?, response.json().await?)),
8114            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8115        }
8116    }
8117
8118    /// Create a repository
8119    ///
8120    /// - `body`: See [`CreateRepoOption`]
8121    pub async fn create_current_user_repo(
8122        &self,
8123        body: CreateRepoOption,
8124    ) -> Result<Repository, ForgejoError> {
8125        let request = self.post("user/repos").json(&body).build()?;
8126        let response = self.execute(request).await?;
8127        match response.status().as_u16() {
8128            201 => Ok(response.json().await?),
8129            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8130        }
8131    }
8132
8133    /// Get user settings
8134    pub async fn get_user_settings(&self) -> Result<UserSettings, ForgejoError> {
8135        let request = self.get("user/settings").build()?;
8136        let response = self.execute(request).await?;
8137        match response.status().as_u16() {
8138            200 => Ok(response.json().await?),
8139            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8140        }
8141    }
8142
8143    /// Update user settings
8144    ///
8145    /// - `body`: See [`UserSettingsOptions`]
8146    pub async fn update_user_settings(
8147        &self,
8148        body: UserSettingsOptions,
8149    ) -> Result<UserSettings, ForgejoError> {
8150        let request = self.patch("user/settings").json(&body).build()?;
8151        let response = self.execute(request).await?;
8152        match response.status().as_u16() {
8153            200 => Ok(response.json().await?),
8154            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8155        }
8156    }
8157
8158    /// The repos that the authenticated user has starred
8159    ///
8160    pub async fn user_current_list_starred(
8161        &self,
8162        query: UserCurrentListStarredQuery,
8163    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8164        let request = self.get(&format!("user/starred?{query}")).build()?;
8165        let response = self.execute(request).await?;
8166        match response.status().as_u16() {
8167            200 => Ok((response.headers().try_into()?, response.json().await?)),
8168            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8169        }
8170    }
8171
8172    /// Whether the authenticated is starring the repo
8173    ///
8174    /// - `owner`: owner of the repo
8175    /// - `repo`: name of the repo
8176    pub async fn user_current_check_starring(
8177        &self,
8178        owner: &str,
8179        repo: &str,
8180    ) -> Result<(), ForgejoError> {
8181        let request = self.get(&format!("user/starred/{owner}/{repo}")).build()?;
8182        let response = self.execute(request).await?;
8183        match response.status().as_u16() {
8184            204 => Ok(()),
8185            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8186        }
8187    }
8188
8189    /// Star the given repo
8190    ///
8191    /// - `owner`: owner of the repo to star
8192    /// - `repo`: name of the repo to star
8193    pub async fn user_current_put_star(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
8194        let request = self.put(&format!("user/starred/{owner}/{repo}")).build()?;
8195        let response = self.execute(request).await?;
8196        match response.status().as_u16() {
8197            204 => Ok(()),
8198            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8199        }
8200    }
8201
8202    /// Unstar the given repo
8203    ///
8204    /// - `owner`: owner of the repo to unstar
8205    /// - `repo`: name of the repo to unstar
8206    pub async fn user_current_delete_star(
8207        &self,
8208        owner: &str,
8209        repo: &str,
8210    ) -> Result<(), ForgejoError> {
8211        let request = self
8212            .delete(&format!("user/starred/{owner}/{repo}"))
8213            .build()?;
8214        let response = self.execute(request).await?;
8215        match response.status().as_u16() {
8216            204 => Ok(()),
8217            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8218        }
8219    }
8220
8221    /// Get list of all existing stopwatches
8222    ///
8223    pub async fn user_get_stop_watches(
8224        &self,
8225        query: UserGetStopWatchesQuery,
8226    ) -> Result<(StopWatchListHeaders, Vec<StopWatch>), ForgejoError> {
8227        let request = self.get(&format!("user/stopwatches?{query}")).build()?;
8228        let response = self.execute(request).await?;
8229        match response.status().as_u16() {
8230            200 => Ok((response.headers().try_into()?, response.json().await?)),
8231            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8232        }
8233    }
8234
8235    /// List repositories watched by the authenticated user
8236    ///
8237    pub async fn user_current_list_subscriptions(
8238        &self,
8239        query: UserCurrentListSubscriptionsQuery,
8240    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8241        let request = self.get(&format!("user/subscriptions?{query}")).build()?;
8242        let response = self.execute(request).await?;
8243        match response.status().as_u16() {
8244            200 => Ok((response.headers().try_into()?, response.json().await?)),
8245            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8246        }
8247    }
8248
8249    /// List all the teams a user belongs to
8250    ///
8251    pub async fn user_list_teams(
8252        &self,
8253        query: UserListTeamsQuery,
8254    ) -> Result<(TeamListHeaders, Vec<Team>), ForgejoError> {
8255        let request = self.get(&format!("user/teams?{query}")).build()?;
8256        let response = self.execute(request).await?;
8257        match response.status().as_u16() {
8258            200 => Ok((response.headers().try_into()?, response.json().await?)),
8259            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8260        }
8261    }
8262
8263    /// List the current user's tracked times
8264    ///
8265    pub async fn user_current_tracked_times(
8266        &self,
8267        query: UserCurrentTrackedTimesQuery,
8268    ) -> Result<(TrackedTimeListHeaders, Vec<TrackedTime>), ForgejoError> {
8269        let request = self.get(&format!("user/times?{query}")).build()?;
8270        let response = self.execute(request).await?;
8271        match response.status().as_u16() {
8272            200 => Ok((response.headers().try_into()?, response.json().await?)),
8273            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8274        }
8275    }
8276
8277    /// Unblocks a user from the doer.
8278    ///
8279    /// - `username`: username of the user
8280    pub async fn user_unblock_user(&self, username: &str) -> Result<(), ForgejoError> {
8281        let request = self.put(&format!("user/unblock/{username}")).build()?;
8282        let response = self.execute(request).await?;
8283        match response.status().as_u16() {
8284            204 => Ok(()),
8285            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8286        }
8287    }
8288
8289    /// Search for users
8290    ///
8291    pub async fn user_search(
8292        &self,
8293        query: UserSearchQuery,
8294    ) -> Result<UserSearchResponse, ForgejoError> {
8295        let request = self.get(&format!("users/search?{query}")).build()?;
8296        let response = self.execute(request).await?;
8297        match response.status().as_u16() {
8298            200 => Ok(response.json().await?),
8299            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8300        }
8301    }
8302
8303    /// Get a user
8304    ///
8305    /// - `username`: username of user to get
8306    pub async fn user_get(&self, username: &str) -> Result<User, ForgejoError> {
8307        let request = self.get(&format!("users/{username}")).build()?;
8308        let response = self.execute(request).await?;
8309        match response.status().as_u16() {
8310            200 => Ok(response.json().await?),
8311            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8312        }
8313    }
8314
8315    /// List a user's activity feeds
8316    ///
8317    /// - `username`: username of user
8318    pub async fn user_list_activity_feeds(
8319        &self,
8320        username: &str,
8321        query: UserListActivityFeedsQuery,
8322    ) -> Result<(ActivityFeedsListHeaders, Vec<Activity>), ForgejoError> {
8323        let request = self
8324            .get(&format!("users/{username}/activities/feeds?{query}"))
8325            .build()?;
8326        let response = self.execute(request).await?;
8327        match response.status().as_u16() {
8328            200 => Ok((response.headers().try_into()?, response.json().await?)),
8329            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8330        }
8331    }
8332
8333    /// List the given user's followers
8334    ///
8335    /// - `username`: username of user
8336    pub async fn user_list_followers(
8337        &self,
8338        username: &str,
8339        query: UserListFollowersQuery,
8340    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
8341        let request = self
8342            .get(&format!("users/{username}/followers?{query}"))
8343            .build()?;
8344        let response = self.execute(request).await?;
8345        match response.status().as_u16() {
8346            200 => Ok((response.headers().try_into()?, response.json().await?)),
8347            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8348        }
8349    }
8350
8351    /// List the users that the given user is following
8352    ///
8353    /// - `username`: username of user
8354    pub async fn user_list_following(
8355        &self,
8356        username: &str,
8357        query: UserListFollowingQuery,
8358    ) -> Result<(UserListHeaders, Vec<User>), ForgejoError> {
8359        let request = self
8360            .get(&format!("users/{username}/following?{query}"))
8361            .build()?;
8362        let response = self.execute(request).await?;
8363        match response.status().as_u16() {
8364            200 => Ok((response.headers().try_into()?, response.json().await?)),
8365            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8366        }
8367    }
8368
8369    /// Check if one user is following another user
8370    ///
8371    /// - `username`: username of following user
8372    /// - `target`: username of followed user
8373    pub async fn user_check_following(
8374        &self,
8375        username: &str,
8376        target: &str,
8377    ) -> Result<(), ForgejoError> {
8378        let request = self
8379            .get(&format!("users/{username}/following/{target}"))
8380            .build()?;
8381        let response = self.execute(request).await?;
8382        match response.status().as_u16() {
8383            204 => Ok(()),
8384            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8385        }
8386    }
8387
8388    /// List the given user's GPG keys
8389    ///
8390    /// - `username`: username of user
8391    pub async fn user_list_gpg_keys(
8392        &self,
8393        username: &str,
8394        query: UserListGpgKeysQuery,
8395    ) -> Result<(GpgKeyListHeaders, Vec<GPGKey>), ForgejoError> {
8396        let request = self
8397            .get(&format!("users/{username}/gpg_keys?{query}"))
8398            .build()?;
8399        let response = self.execute(request).await?;
8400        match response.status().as_u16() {
8401            200 => Ok((response.headers().try_into()?, response.json().await?)),
8402            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8403        }
8404    }
8405
8406    /// Get a user's heatmap
8407    ///
8408    /// - `username`: username of user to get
8409    pub async fn user_get_heatmap_data(
8410        &self,
8411        username: &str,
8412    ) -> Result<Vec<UserHeatmapData>, ForgejoError> {
8413        let request = self.get(&format!("users/{username}/heatmap")).build()?;
8414        let response = self.execute(request).await?;
8415        match response.status().as_u16() {
8416            200 => Ok(response.json().await?),
8417            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8418        }
8419    }
8420
8421    /// List the given user's public keys
8422    ///
8423    /// - `username`: username of user
8424    pub async fn user_list_keys(
8425        &self,
8426        username: &str,
8427        query: UserListKeysQuery,
8428    ) -> Result<(PublicKeyListHeaders, Vec<PublicKey>), ForgejoError> {
8429        let request = self
8430            .get(&format!("users/{username}/keys?{query}"))
8431            .build()?;
8432        let response = self.execute(request).await?;
8433        match response.status().as_u16() {
8434            200 => Ok((response.headers().try_into()?, response.json().await?)),
8435            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8436        }
8437    }
8438
8439    /// List a user's organizations
8440    ///
8441    /// - `username`: username of user
8442    pub async fn org_list_user_orgs(
8443        &self,
8444        username: &str,
8445        query: OrgListUserOrgsQuery,
8446    ) -> Result<(OrganizationListHeaders, Vec<Organization>), ForgejoError> {
8447        let request = self
8448            .get(&format!("users/{username}/orgs?{query}"))
8449            .build()?;
8450        let response = self.execute(request).await?;
8451        match response.status().as_u16() {
8452            200 => Ok((response.headers().try_into()?, response.json().await?)),
8453            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8454        }
8455    }
8456
8457    /// Get user permissions in organization
8458    ///
8459    /// - `username`: username of user
8460    /// - `org`: name of the organization
8461    pub async fn org_get_user_permissions(
8462        &self,
8463        username: &str,
8464        org: &str,
8465    ) -> Result<OrganizationPermissions, ForgejoError> {
8466        let request = self
8467            .get(&format!("users/{username}/orgs/{org}/permissions"))
8468            .build()?;
8469        let response = self.execute(request).await?;
8470        match response.status().as_u16() {
8471            200 => Ok(response.json().await?),
8472            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8473        }
8474    }
8475
8476    /// List the repos owned by the given user
8477    ///
8478    /// - `username`: username of user
8479    pub async fn user_list_repos(
8480        &self,
8481        username: &str,
8482        query: UserListReposQuery,
8483    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8484        let request = self
8485            .get(&format!("users/{username}/repos?{query}"))
8486            .build()?;
8487        let response = self.execute(request).await?;
8488        match response.status().as_u16() {
8489            200 => Ok((response.headers().try_into()?, response.json().await?)),
8490            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8491        }
8492    }
8493
8494    /// The repos that the given user has starred
8495    ///
8496    /// - `username`: username of user
8497    pub async fn user_list_starred(
8498        &self,
8499        username: &str,
8500        query: UserListStarredQuery,
8501    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8502        let request = self
8503            .get(&format!("users/{username}/starred?{query}"))
8504            .build()?;
8505        let response = self.execute(request).await?;
8506        match response.status().as_u16() {
8507            200 => Ok((response.headers().try_into()?, response.json().await?)),
8508            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8509        }
8510    }
8511
8512    /// List the repositories watched by a user
8513    ///
8514    /// - `username`: username of the user
8515    pub async fn user_list_subscriptions(
8516        &self,
8517        username: &str,
8518        query: UserListSubscriptionsQuery,
8519    ) -> Result<(RepositoryListHeaders, Vec<Repository>), ForgejoError> {
8520        let request = self
8521            .get(&format!("users/{username}/subscriptions?{query}"))
8522            .build()?;
8523        let response = self.execute(request).await?;
8524        match response.status().as_u16() {
8525            200 => Ok((response.headers().try_into()?, response.json().await?)),
8526            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8527        }
8528    }
8529
8530    /// List the authenticated user's access tokens
8531    ///
8532    /// - `username`: username of user
8533    pub async fn user_get_tokens(
8534        &self,
8535        username: &str,
8536        query: UserGetTokensQuery,
8537    ) -> Result<(AccessTokenListHeaders, Vec<AccessToken>), ForgejoError> {
8538        let request = self
8539            .get(&format!("users/{username}/tokens?{query}"))
8540            .build()?;
8541        let response = self.execute(request).await?;
8542        match response.status().as_u16() {
8543            200 => Ok((response.headers().try_into()?, response.json().await?)),
8544            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8545        }
8546    }
8547
8548    /// Create an access token
8549    ///
8550    /// - `username`: username of user
8551    /// - `body`: See [`CreateAccessTokenOption`]
8552    pub async fn user_create_token(
8553        &self,
8554        username: &str,
8555        body: CreateAccessTokenOption,
8556    ) -> Result<AccessToken, ForgejoError> {
8557        let request = self
8558            .post(&format!("users/{username}/tokens"))
8559            .json(&body)
8560            .build()?;
8561        let response = self.execute(request).await?;
8562        match response.status().as_u16() {
8563            201 => Ok(response.json().await?),
8564            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8565        }
8566    }
8567
8568    /// delete an access token
8569    ///
8570    /// - `username`: username of user
8571    /// - `token`: token to be deleted, identified by ID and if not available by name
8572    pub async fn user_delete_access_token(
8573        &self,
8574        username: &str,
8575        token: &str,
8576    ) -> Result<(), ForgejoError> {
8577        let request = self
8578            .delete(&format!("users/{username}/tokens/{token}"))
8579            .build()?;
8580        let response = self.execute(request).await?;
8581        match response.status().as_u16() {
8582            204 => Ok(()),
8583            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8584        }
8585    }
8586
8587    /// Returns the version of the Forgejo application
8588    pub async fn get_version(&self) -> Result<ServerVersion, ForgejoError> {
8589        let request = self.get("version").build()?;
8590        let response = self.execute(request).await?;
8591        match response.status().as_u16() {
8592            200 => Ok(response.json().await?),
8593            _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
8594        }
8595    }
8596}