cod_client/specialized_requests/
mod.rs1use chrono::DateTime;
2use chrono::Utc;
3use cod_endpoints::endpoint_generator::EndpointGenerator;
4use cod_types::api::branch::Branch;
5use cod_types::api::comment::Comment;
6use cod_types::api::create_options::create_comment_option::CreateCommentOption;
7use cod_types::api::create_options::create_fork_option::CreateForkOption;
8use cod_types::api::issue::Issue;
9use cod_types::api::issue_labels_option::IssueLabelsOption;
10use cod_types::api::label::Label;
11use cod_types::api::milestone::Milestone;
12use cod_types::api::notification::notification_state_type::NotificationStateType;
13use cod_types::api::notification::notification_thread::NotificationThread;
14use cod_types::api::notification::notification_type::NotificationSubjectType;
15use cod_types::api::pull_request::PullRequest;
16use cod_types::api::repository::Repository;
17use cod_types::api::search_results::SearchResults;
18use cod_types::api::state_type::StateType;
19use cod_types::api::user::User;
20use reqwest::Url;
21use serde::de::DeserializeOwned;
22use std::fmt::Debug;
23
24use crate::CodebergClient;
25
26impl CodebergClient {
27 pub async fn get_user_info(&self) -> anyhow::Result<User> {
28 let api = EndpointGenerator::user_info()?;
29 self.get(api).await
30 }
31
32 pub async fn get_all_repos_info(&self) -> anyhow::Result<Vec<Repository>> {
33 let api = EndpointGenerator::user_repos()?;
34 self.get(api).await
35 }
36
37 pub async fn get_repo_info(&self) -> anyhow::Result<Repository> {
38 let api = EndpointGenerator::repo_infos()?;
39 self.get(api).await
40 }
41
42 pub async fn get_repo_labels(&self, maybe_limit: Option<usize>) -> anyhow::Result<Vec<Label>> {
43 let api = EndpointGenerator::repo_labels()?;
44 if let Some(limit) = maybe_limit {
45 self.get_query(api, [("limit", limit)]).await
46 } else {
47 self.get(api).await
48 }
49 }
50
51 pub async fn get_state_limit_list<T>(
52 &self,
53 maybe_state: Option<StateType>,
54 maybe_limit: Option<usize>,
55 api: Url,
56 ) -> anyhow::Result<T>
57 where
58 T: DeserializeOwned + Debug,
59 {
60 use std::iter::once;
61
62 let query_args = once((
63 "limit",
64 maybe_limit.map_or_else(|| usize::MAX.to_string(), |limit| limit.to_string()),
65 ))
66 .chain(once((
67 "state",
68 maybe_state.unwrap_or(StateType::All).to_string(),
69 )))
70 .collect::<Vec<_>>();
71 if query_args.is_empty() {
72 self.get(api).await
73 } else {
74 self.get_query(api, query_args).await
75 }
76 }
77
78 pub async fn get_repo_milestones(
79 &self,
80 maybe_state: Option<StateType>,
81 maybe_limit: Option<usize>,
82 ) -> anyhow::Result<Vec<Milestone>> {
83 let api = EndpointGenerator::repo_milestones()?;
84 self.get_state_limit_list(maybe_state, maybe_limit, api)
85 .await
86 }
87
88 pub async fn get_repo_issues(
89 &self,
90 maybe_state: Option<StateType>,
91 maybe_limit: Option<usize>,
92 ) -> anyhow::Result<Vec<Issue>> {
93 let api = EndpointGenerator::repo_issues()?;
94 self.get_state_limit_list(maybe_state, maybe_limit, api)
95 .await
96 }
97
98 pub async fn get_repo_prs(
99 &self,
100 maybe_state: Option<StateType>,
101 maybe_limit: Option<usize>,
102 ) -> anyhow::Result<Vec<PullRequest>> {
103 let api = EndpointGenerator::repo_pull_requests()?;
104 self.get_state_limit_list(maybe_state, maybe_limit, api)
105 .await
106 }
107
108 pub async fn get_repo_assignees(&self) -> anyhow::Result<Vec<User>> {
109 let api = EndpointGenerator::repo_assignees()?;
110 self.get(api).await
111 }
112
113 pub async fn search_for_user(
114 &self,
115 username: &str,
116 ) -> anyhow::Result<SearchResults<Vec<User>>> {
117 let api = EndpointGenerator::user_search()?;
118 self.get_query(api, [("q", username)]).await
119 }
120
121 pub async fn search_for_repo(
122 &self,
123 reponame: &str,
124 user_id: usize,
125 ) -> anyhow::Result<SearchResults<Vec<Repository>>> {
126 let api = EndpointGenerator::repo_search()?;
127 self.get_query(
128 api,
129 [("q", reponame.to_string()), ("uid", user_id.to_string())],
130 )
131 .await
132 }
133
134 pub async fn fork_repo(&self, ownername: &str, reponame: &str) -> anyhow::Result<Repository> {
135 let api = EndpointGenerator::repo_forks(ownername, reponame)?;
136 let body = CreateForkOption::same_repo_name();
137 self.post_query_body(api, body, [("owner", ownername), ("repo", reponame)])
138 .await
139 }
140
141 pub async fn get_comments_for_id(&self, issue_or_pr_id: usize) -> anyhow::Result<Vec<Comment>> {
142 let api = EndpointGenerator::repo_comments_for_id(issue_or_pr_id)?;
143 self.get(api).await
144 }
145
146 pub async fn post_comment_for_id(
147 &self,
148 issue_id: usize,
149 comment: CreateCommentOption,
150 ) -> anyhow::Result<Comment> {
151 let api = EndpointGenerator::repo_comments_for_id(issue_id)?;
152 self.post_body(api, comment).await
153 }
154
155 pub async fn delete_label(&self, label_id: usize) -> anyhow::Result<()> {
156 let api = EndpointGenerator::repo_labels_with_id(label_id)?;
157 self.delete(api).await
158 }
159
160 pub async fn get_repo_branches(&self) -> anyhow::Result<Vec<Branch>> {
161 let api = EndpointGenerator::repo_branches()?;
162 self.get(api).await
163 }
164
165 pub async fn get_user_repos(&self, username: String) -> anyhow::Result<Vec<Repository>> {
166 let api = EndpointGenerator::get_user_repos(username)?;
167 self.get(api).await
168 }
169
170 pub async fn get_org_repos(&self, orgname: String) -> anyhow::Result<Vec<Repository>> {
171 let api = EndpointGenerator::get_org_repos(orgname)?;
172 self.get(api).await
173 }
174
175 pub async fn get_user_or_org_repos(&self, name: String) -> anyhow::Result<Vec<Repository>> {
176 self.get_org_repos(name.clone())
177 .await
178 .or(self.get_user_repos(name).await)
179 }
180
181 pub async fn replace_labels(
182 &self,
183 issue_id: usize,
184 issue_labels_option: IssueLabelsOption,
185 ) -> anyhow::Result<Vec<Label>> {
186 let api = EndpointGenerator::repo_put_issue_labels(issue_id)?;
187 self.put_body(api, issue_labels_option).await
188 }
189
190 pub async fn get_all_notifications_unfiltered(
191 &self,
192 all: bool,
193 ) -> anyhow::Result<Vec<NotificationThread>> {
194 self.get_all_notifications_filtered(
195 all,
196 None,
197 None,
198 vec![NotificationStateType::Pinned, NotificationStateType::Unread],
199 None,
200 1,
201 100000,
202 )
203 .await
204 }
205
206 pub async fn get_all_notifications_filtered(
207 &self,
208 all: bool,
209 since: Option<DateTime<Utc>>,
210 before: Option<DateTime<Utc>>,
211 status_types: Vec<NotificationStateType>,
212 subject_type: Option<NotificationSubjectType>,
213 page: usize,
214 limit: usize,
215 ) -> anyhow::Result<Vec<NotificationThread>> {
216 use std::iter::once;
217 let api = EndpointGenerator::all_notifications()?;
218 let query = since
219 .iter()
220 .map(|since| ("since", since.to_rfc3339()))
221 .chain(before.iter().map(|before| ("before", before.to_rfc3339())))
222 .chain(
223 status_types
224 .iter()
225 .map(|status_type| ("status-types", status_type.to_string())),
226 )
227 .chain(
228 subject_type
229 .iter()
230 .map(|subject_type| ("subject-type", subject_type.to_string())),
231 )
232 .chain(once(("page", page.to_string())))
233 .chain(once(("limit", limit.to_string())))
234 .chain(once(("all", all.to_string())))
235 .collect::<Vec<_>>();
236 self.get_query(api, query).await
237 }
238
239 pub async fn get_notification_thread(
240 &self,
241 thread_id: usize,
242 ) -> anyhow::Result<NotificationThread> {
243 let api = EndpointGenerator::get_notification_thread(thread_id)?;
244 self.get(api).await
245 }
246}