1use crate::error::{ApiError, Result};
4use reqwest::Client;
5use serde_json::Value;
6use url::Url;
7
8pub struct IssuesClient {
10 base_url: String,
11 client: Client,
12}
13
14impl IssuesClient {
15 pub fn new(base_url: String, client: Client) -> Self {
17 Self { base_url, client }
18 }
19
20 pub fn with_auth(self, token: &str) -> Self {
22 self
24 }
25
26 pub async fn get_repo_issues_number(
28 &self,
29 repo: String,
30 number: i64,
31 ) -> Result<Value> {
32 let path = format!("/{}/-/issues/{}", repo, number);
33 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
34
35
36 let request = self.client.request(
37 reqwest::Method::GET,
38 url
39 );
40
41
42
43
44 let response = request.send().await?;
45
46 if response.status().is_success() {
47 let json: Value = response.json().await?;
48 Ok(json)
49 } else {
50 Err(ApiError::HttpError(response.status().as_u16()))
51 }
52 }
53
54 pub async fn patch_repo_issues_number(
56 &self,
57 repo: String,
58 number: i64,
59 patch_issue_form: serde_json::Value,
60 ) -> Result<Value> {
61 let path = format!("/{}/-/issues/{}", repo, number);
62 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
63
64
65
66 let mut request = self.client.request(
67 reqwest::Method::PATCH,
68 url
69 );
70
71
72
73 request = request.json(&patch_issue_form);
74
75 let response = request.send().await?;
76
77 if response.status().is_success() {
78 let json: Value = response.json().await?;
79 Ok(json)
80 } else {
81 Err(ApiError::HttpError(response.status().as_u16()))
82 }
83 }
84
85 pub async fn delete_repo_issues_number_labels_name(
87 &self,
88 repo: String,
89 number: i64,
90 name: String,
91 ) -> Result<Value> {
92 let path = format!("/{}/-/issues/{}/labels/{}", repo, number, name);
93 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
94
95
96 let request = self.client.request(
97 reqwest::Method::DELETE,
98 url
99 );
100
101
102
103
104 let response = request.send().await?;
105
106 if response.status().is_success() {
107 let json: Value = response.json().await?;
108 Ok(json)
109 } else {
110 Err(ApiError::HttpError(response.status().as_u16()))
111 }
112 }
113
114 pub async fn get_repo_issues_number_assignees(
116 &self,
117 repo: String,
118 number: String,
119 ) -> Result<Value> {
120 let path = format!("/{}/-/issues/{}/assignees", repo, number);
121 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
122
123
124 let request = self.client.request(
125 reqwest::Method::GET,
126 url
127 );
128
129
130
131
132 let response = request.send().await?;
133
134 if response.status().is_success() {
135 let json: Value = response.json().await?;
136 Ok(json)
137 } else {
138 Err(ApiError::HttpError(response.status().as_u16()))
139 }
140 }
141
142 pub async fn post_repo_issues_number_assignees(
144 &self,
145 repo: String,
146 number: String,
147 post_issue_assignees_form: serde_json::Value,
148 ) -> Result<Value> {
149 let path = format!("/{}/-/issues/{}/assignees", repo, number);
150 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
151
152
153
154 let mut request = self.client.request(
155 reqwest::Method::POST,
156 url
157 );
158
159
160
161 request = request.json(&post_issue_assignees_form);
162
163 let response = request.send().await?;
164
165 if response.status().is_success() {
166 let json: Value = response.json().await?;
167 Ok(json)
168 } else {
169 Err(ApiError::HttpError(response.status().as_u16()))
170 }
171 }
172
173 pub async fn delete_repo_issues_number_assignees(
175 &self,
176 repo: String,
177 number: String,
178 delete_issue_assignees_form: serde_json::Value,
179 ) -> Result<Value> {
180 let path = format!("/{}/-/issues/{}/assignees", repo, number);
181 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
182
183
184
185 let mut request = self.client.request(
186 reqwest::Method::DELETE,
187 url
188 );
189
190
191
192 request = request.json(&delete_issue_assignees_form);
193
194 let response = request.send().await?;
195
196 if response.status().is_success() {
197 let json: Value = response.json().await?;
198 Ok(json)
199 } else {
200 Err(ApiError::HttpError(response.status().as_u16()))
201 }
202 }
203
204 pub async fn patch_repo_issues_number_assignees(
206 &self,
207 repo: String,
208 number: String,
209 patch_issue_assignees_form: serde_json::Value,
210 ) -> Result<Value> {
211 let path = format!("/{}/-/issues/{}/assignees", repo, number);
212 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
213
214
215
216 let mut request = self.client.request(
217 reqwest::Method::PATCH,
218 url
219 );
220
221
222
223 request = request.json(&patch_issue_assignees_form);
224
225 let response = request.send().await?;
226
227 if response.status().is_success() {
228 let json: Value = response.json().await?;
229 Ok(json)
230 } else {
231 Err(ApiError::HttpError(response.status().as_u16()))
232 }
233 }
234
235 pub async fn get_repo_issues_number_comments(
237 &self,
238 repo: String,
239 number: i64,
240 page: Option<i64>,
241 page_size: Option<i64>,
242 ) -> Result<Value> {
243 let path = format!("/{}/-/issues/{}/comments", repo, number);
244 let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
245
246 if let Some(value) = page {
247 url.query_pairs_mut().append_pair("page", &value.to_string());
248 }
249 if let Some(value) = page_size {
250 url.query_pairs_mut().append_pair("page_size", &value.to_string());
251 }
252
253 let request = self.client.request(
254 reqwest::Method::GET,
255 url
256 );
257
258
259
260
261 let response = request.send().await?;
262
263 if response.status().is_success() {
264 let json: Value = response.json().await?;
265 Ok(json)
266 } else {
267 Err(ApiError::HttpError(response.status().as_u16()))
268 }
269 }
270
271 pub async fn post_repo_issues_number_comments(
273 &self,
274 repo: String,
275 number: i64,
276 post_issue_comment_form: serde_json::Value,
277 ) -> Result<Value> {
278 let path = format!("/{}/-/issues/{}/comments", repo, number);
279 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
280
281
282
283 let mut request = self.client.request(
284 reqwest::Method::POST,
285 url
286 );
287
288
289
290 request = request.json(&post_issue_comment_form);
291
292 let response = request.send().await?;
293
294 if response.status().is_success() {
295 let json: Value = response.json().await?;
296 Ok(json)
297 } else {
298 Err(ApiError::HttpError(response.status().as_u16()))
299 }
300 }
301
302 pub async fn get_repo_issues_number_assignees_assignee(
304 &self,
305 repo: String,
306 number: String,
307 assignee: String,
308 ) -> Result<Value> {
309 let path = format!("/{}/-/issues/{}/assignees/{}", repo, number, assignee);
310 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
311
312
313 let request = self.client.request(
314 reqwest::Method::GET,
315 url
316 );
317
318
319
320
321 let response = request.send().await?;
322
323 if response.status().is_success() {
324 let json: Value = response.json().await?;
325 Ok(json)
326 } else {
327 Err(ApiError::HttpError(response.status().as_u16()))
328 }
329 }
330
331 pub async fn get_repo_issues(
333 &self,
334 repo: String,
335 page: Option<i64>,
336 page_size: Option<i64>,
337 state: Option<String>,
338 keyword: Option<String>,
339 priority: Option<String>,
340 labels: Option<String>,
341 authors: Option<String>,
342 assignees: Option<String>,
343 updated_time_begin: Option<String>,
344 updated_time_end: Option<String>,
345 close_time_begin: Option<String>,
346 close_time_end: Option<String>,
347 order_by: Option<String>,
348 ) -> Result<Value> {
349 let path = format!("/{}/-/issues", repo);
350 let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
351
352 if let Some(value) = page {
353 url.query_pairs_mut().append_pair("page", &value.to_string());
354 }
355 if let Some(value) = page_size {
356 url.query_pairs_mut().append_pair("page_size", &value.to_string());
357 }
358 if let Some(value) = state {
359 url.query_pairs_mut().append_pair("state", &value.to_string());
360 }
361 if let Some(value) = keyword {
362 url.query_pairs_mut().append_pair("keyword", &value.to_string());
363 }
364 if let Some(value) = priority {
365 url.query_pairs_mut().append_pair("priority", &value.to_string());
366 }
367 if let Some(value) = labels {
368 url.query_pairs_mut().append_pair("labels", &value.to_string());
369 }
370 if let Some(value) = authors {
371 url.query_pairs_mut().append_pair("authors", &value.to_string());
372 }
373 if let Some(value) = assignees {
374 url.query_pairs_mut().append_pair("assignees", &value.to_string());
375 }
376 if let Some(value) = updated_time_begin {
377 url.query_pairs_mut().append_pair("updated_time_begin", &value.to_string());
378 }
379 if let Some(value) = updated_time_end {
380 url.query_pairs_mut().append_pair("updated_time_end", &value.to_string());
381 }
382 if let Some(value) = close_time_begin {
383 url.query_pairs_mut().append_pair("close_time_begin", &value.to_string());
384 }
385 if let Some(value) = close_time_end {
386 url.query_pairs_mut().append_pair("close_time_end", &value.to_string());
387 }
388 if let Some(value) = order_by {
389 url.query_pairs_mut().append_pair("order_by", &value.to_string());
390 }
391
392 let request = self.client.request(
393 reqwest::Method::GET,
394 url
395 );
396
397
398
399
400 let response = request.send().await?;
401
402 if response.status().is_success() {
403 let json: Value = response.json().await?;
404 Ok(json)
405 } else {
406 Err(ApiError::HttpError(response.status().as_u16()))
407 }
408 }
409
410 pub async fn post_repo_issues(
412 &self,
413 repo: String,
414 post_issue_form: serde_json::Value,
415 ) -> Result<Value> {
416 let path = format!("/{}/-/issues", repo);
417 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
418
419
420
421 let mut request = self.client.request(
422 reqwest::Method::POST,
423 url
424 );
425
426
427
428 request = request.json(&post_issue_form);
429
430 let response = request.send().await?;
431
432 if response.status().is_success() {
433 let json: Value = response.json().await?;
434 Ok(json)
435 } else {
436 Err(ApiError::HttpError(response.status().as_u16()))
437 }
438 }
439
440 pub async fn get_repo_issues_number_labels(
442 &self,
443 repo: String,
444 number: i64,
445 page: Option<i64>,
446 page_size: Option<i64>,
447 ) -> Result<Value> {
448 let path = format!("/{}/-/issues/{}/labels", repo, number);
449 let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
450
451 if let Some(value) = page {
452 url.query_pairs_mut().append_pair("page", &value.to_string());
453 }
454 if let Some(value) = page_size {
455 url.query_pairs_mut().append_pair("page_size", &value.to_string());
456 }
457
458 let request = self.client.request(
459 reqwest::Method::GET,
460 url
461 );
462
463
464
465
466 let response = request.send().await?;
467
468 if response.status().is_success() {
469 let json: Value = response.json().await?;
470 Ok(json)
471 } else {
472 Err(ApiError::HttpError(response.status().as_u16()))
473 }
474 }
475
476 pub async fn post_repo_issues_number_labels(
478 &self,
479 repo: String,
480 number: i64,
481 post_issue_labels_form: serde_json::Value,
482 ) -> Result<Value> {
483 let path = format!("/{}/-/issues/{}/labels", repo, number);
484 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
485
486
487
488 let mut request = self.client.request(
489 reqwest::Method::POST,
490 url
491 );
492
493
494
495 request = request.json(&post_issue_labels_form);
496
497 let response = request.send().await?;
498
499 if response.status().is_success() {
500 let json: Value = response.json().await?;
501 Ok(json)
502 } else {
503 Err(ApiError::HttpError(response.status().as_u16()))
504 }
505 }
506
507 pub async fn put_repo_issues_number_labels(
509 &self,
510 repo: String,
511 number: i64,
512 put_issue_labels_form: serde_json::Value,
513 ) -> Result<Value> {
514 let path = format!("/{}/-/issues/{}/labels", repo, number);
515 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
516
517
518
519 let mut request = self.client.request(
520 reqwest::Method::PUT,
521 url
522 );
523
524
525
526 request = request.json(&put_issue_labels_form);
527
528 let response = request.send().await?;
529
530 if response.status().is_success() {
531 let json: Value = response.json().await?;
532 Ok(json)
533 } else {
534 Err(ApiError::HttpError(response.status().as_u16()))
535 }
536 }
537
538 pub async fn delete_repo_issues_number_labels(
540 &self,
541 repo: String,
542 number: i64,
543 ) -> Result<Value> {
544 let path = format!("/{}/-/issues/{}/labels", repo, number);
545 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
546
547
548 let request = self.client.request(
549 reqwest::Method::DELETE,
550 url
551 );
552
553
554
555
556 let response = request.send().await?;
557
558 if response.status().is_success() {
559 let json: Value = response.json().await?;
560 Ok(json)
561 } else {
562 Err(ApiError::HttpError(response.status().as_u16()))
563 }
564 }
565
566 pub async fn get_repo_issues_number_comments_comment_id(
568 &self,
569 repo: String,
570 number: String,
571 comment_id: String,
572 ) -> Result<Value> {
573 let path = format!("/{}/-/issues/{}/comments/{}", repo, number, comment_id);
574 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
575
576
577 let request = self.client.request(
578 reqwest::Method::GET,
579 url
580 );
581
582
583
584
585 let response = request.send().await?;
586
587 if response.status().is_success() {
588 let json: Value = response.json().await?;
589 Ok(json)
590 } else {
591 Err(ApiError::HttpError(response.status().as_u16()))
592 }
593 }
594
595 pub async fn patch_repo_issues_number_comments_comment_id(
597 &self,
598 repo: String,
599 number: i64,
600 comment_id: i64,
601 patch_issue_comment_form: serde_json::Value,
602 ) -> Result<Value> {
603 let path = format!("/{}/-/issues/{}/comments/{}", repo, number, comment_id);
604 let url = Url::parse(&format!("{}{}", self.base_url, path))?;
605
606
607
608 let mut request = self.client.request(
609 reqwest::Method::PATCH,
610 url
611 );
612
613
614
615 request = request.json(&patch_issue_comment_form);
616
617 let response = request.send().await?;
618
619 if response.status().is_success() {
620 let json: Value = response.json().await?;
621 Ok(json)
622 } else {
623 Err(ApiError::HttpError(response.status().as_u16()))
624 }
625 }
626
627}