strava_wrapper/filters/
uploads.rs1use crate::models::Upload;
2use crate::query::{
3 get_with_query_and_path, post_multipart, Endpoint, ErrorWrapper, PathQuery, Query, Sendable, ID,
4};
5use async_trait::async_trait;
6use reqwest::multipart::{Form, Part};
7use std::collections::HashMap;
8use strava_wrapper_macros::{Endpoint, PathQuery, Query, ID};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum UploadDataType {
14 Fit,
15 FitGz,
16 Tcx,
17 TcxGz,
18 Gpx,
19 GpxGz,
20}
21
22impl UploadDataType {
23 pub fn as_str(self) -> &'static str {
24 match self {
25 Self::Fit => "fit",
26 Self::FitGz => "fit.gz",
27 Self::Tcx => "tcx",
28 Self::TcxGz => "tcx.gz",
29 Self::Gpx => "gpx",
30 Self::GpxGz => "gpx.gz",
31 }
32 }
33}
34
35#[must_use = "this request is not executed until you call .send().await"]
39pub struct UploadActivity {
40 url: String,
41 token: String,
42 file: Vec<u8>,
43 data_type: UploadDataType,
44 name: Option<String>,
45 description: Option<String>,
46 trainer: Option<bool>,
47 commute: Option<bool>,
48 external_id: Option<String>,
49}
50
51impl UploadActivity {
52 pub fn new(
53 url: impl Into<String>,
54 token: impl Into<String>,
55 file: Vec<u8>,
56 data_type: UploadDataType,
57 ) -> Self {
58 Self {
59 url: url.into(),
60 token: token.into(),
61 file,
62 data_type,
63 name: None,
64 description: None,
65 trainer: None,
66 commute: None,
67 external_id: None,
68 }
69 }
70
71 pub fn name(mut self, name: impl Into<String>) -> Self {
72 self.name = Some(name.into());
73 self
74 }
75
76 pub fn description(mut self, description: impl Into<String>) -> Self {
77 self.description = Some(description.into());
78 self
79 }
80
81 pub fn trainer(mut self, trainer: bool) -> Self {
82 self.trainer = Some(trainer);
83 self
84 }
85
86 pub fn commute(mut self, commute: bool) -> Self {
87 self.commute = Some(commute);
88 self
89 }
90
91 pub fn external_id(mut self, id: impl Into<String>) -> Self {
92 self.external_id = Some(id.into());
93 self
94 }
95}
96
97#[async_trait]
98impl Sendable<Upload> for UploadActivity {
99 async fn send(self) -> Result<Upload, ErrorWrapper> {
100 let endpoint = format!("{}/v3/uploads", self.url);
101
102 let mut form = Form::new()
103 .part(
104 "file",
105 Part::bytes(self.file).file_name(format!("upload.{}", self.data_type.as_str())),
106 )
107 .text("data_type", self.data_type.as_str().to_string());
108
109 if let Some(name) = self.name {
110 form = form.text("name", name);
111 }
112 if let Some(description) = self.description {
113 form = form.text("description", description);
114 }
115 if let Some(trainer) = self.trainer {
116 form = form.text("trainer", (trainer as u8).to_string());
117 }
118 if let Some(commute) = self.commute {
119 form = form.text("commute", (commute as u8).to_string());
120 }
121 if let Some(external_id) = self.external_id {
122 form = form.text("external_id", external_id);
123 }
124
125 post_multipart(&endpoint, &self.token, form).await
126 }
127}
128
129#[derive(Debug, Clone, Endpoint, Query, PathQuery, ID)]
130#[must_use = "this request is not executed until you call .send().await"]
131pub struct GetUpload {
132 url: String,
133 token: String,
134 path: String,
135 query: Vec<(String, String)>,
136 path_params: Vec<(String, String)>,
137}
138
139#[async_trait]
140impl Sendable<Upload> for GetUpload {
141 async fn send(self) -> Result<Upload, ErrorWrapper> {
142 let token = self.token.clone();
143 get_with_query_and_path(self, &token).await
144 }
145}