Skip to main content

votesmart/api/
votes.rs

1use crate::VotesmartProxy;
2use reqwest::{Error, Response};
3
4pub struct Votes<'a>(pub &'a VotesmartProxy);
5
6impl Votes<'_> {
7    /// This method dumps categories that contain released bills according to year and state.
8    pub async fn get_categories(
9        &self,
10        year: i32,
11        state_id: Option<&str>,
12    ) -> Result<Response, Error> {
13        let url = format!(
14            "{base_url}{operation}?key={key}&year={year}&stateId={state_id}&o=JSON",
15            base_url = &self.0.base_url,
16            key = &self.0.api_key,
17            operation = "Votes.getCategories",
18            year = year,
19            state_id = state_id.unwrap_or("")
20        );
21
22        self.0.client.get(url).send().await
23    }
24
25    /// This method dumps general information on a bill.
26    pub async fn get_bill(&self, bill_id: i32) -> Result<Response, Error> {
27        let url = format!(
28            "{base_url}{operation}?key={key}&billId={bill_id}&o=JSON",
29            base_url = &self.0.base_url,
30            key = &self.0.api_key,
31            operation = "Votes.getBill",
32            bill_id = bill_id,
33        );
34
35        self.0.client.get(url).send().await
36    }
37
38    /// This gets detailed action information on a certain stage of the bill.
39    pub async fn get_bill_action(&self, action_id: i32) -> Result<Response, Error> {
40        let url = format!(
41            "{base_url}{operation}?key={key}&actionId={action_id}&o=JSON",
42            base_url = &self.0.base_url,
43            key = &self.0.api_key,
44            operation = "Votes.getBillAction",
45            action_id = action_id,
46        );
47
48        self.0.client.get(url).send().await
49    }
50
51    /// Method provides votes listed by candidate on a certain bill action.
52    pub async fn get_bill_action_votes(&self, action_id: i32) -> Result<Response, Error> {
53        let url = format!(
54            "{base_url}{operation}?key={key}&actionId={action_id}&o=JSON",
55            base_url = &self.0.base_url,
56            key = &self.0.api_key,
57            operation = "Votes.getBillActionVotes",
58            action_id = action_id,
59        );
60
61        self.0.client.get(url).send().await
62    }
63
64    /// Returns a single vote according to official and action.
65    pub async fn get_bill_action_vote_by_official(
66        &self,
67        action_id: i32,
68        candidate_id: i32,
69    ) -> Result<Response, Error> {
70        let url = format!(
71            "{base_url}{operation}?key={key}&actionId={action_id}&candidateId={candidate_id}&o=JSON",
72            base_url = &self.0.base_url,
73            key = &self.0.api_key,
74            operation = "Votes.getBillActionVotesByOfficial",
75            action_id = action_id,
76            candidate_id = candidate_id
77        );
78
79        self.0.client.get(url).send().await
80    }
81
82    /// Returns a list of bills that are like the billNumber input.
83    pub async fn get_by_bill_number(&self, bill_number: String) -> Result<Response, Error> {
84        let url = format!(
85            "{base_url}{operation}?key={key}&billNumber={bill_number}&o=JSON",
86            base_url = &self.0.base_url,
87            key = &self.0.api_key,
88            operation = "Votes.getByBillNumber",
89            bill_number = bill_number,
90        );
91
92        self.0.client.get(url).send().await
93    }
94
95    // Returns a list of bills that fit the category, year, and state input.
96    pub async fn get_bills_by_category_year_state(
97        &self,
98        category_id: i32,
99        year: i32,
100        state_id: Option<&str>,
101    ) -> Result<Response, Error> {
102        let url = format!(
103            "{base_url}{operation}?key={key}&categoryId={category_id}&year={year}&stateId={state_id}&o=JSON",
104            base_url = &self.0.base_url,
105            key = &self.0.api_key,
106            operation = "Votes.getBillsByCategoryYearState",
107            category_id = category_id,
108            year = year,
109            state_id = state_id.unwrap_or("")
110        );
111
112        self.0.client.get(url).send().await
113    }
114
115    /// Returns a list of bills that fit the year and state input.
116    pub async fn get_bills_by_year_state(
117        &self,
118        year: i32,
119        state_id: Option<&str>,
120    ) -> Result<Response, Error> {
121        let url = format!(
122            "{base_url}{operation}?key={key}&year={year}&stateId={state_id}&o=JSON",
123            base_url = &self.0.base_url,
124            key = &self.0.api_key,
125            operation = "Votes.getBillsByYearState",
126            year = year,
127            state_id = state_id.unwrap_or("")
128        );
129
130        self.0.client.get(url).send().await
131    }
132
133    /// Returns a list of bills that fit the candidate and year.
134    pub async fn get_bills_by_official_year_office(
135        &self,
136        candidate_id: i32,
137        year: i32,
138        office_id: Option<&str>,
139    ) -> Result<Response, Error> {
140        let url = format!(
141            "{base_url}{operation}?key={key}&candidateId={candidate_id}&year={year}&officeId={office_id}&o=JSON",
142            base_url = &self.0.base_url,
143            key = &self.0.api_key,
144            operation = "Votes.getByBillNumber",
145            candidate_id = candidate_id,
146            year = year,
147            office_id = office_id.unwrap_or("")
148        );
149
150        self.0.client.get(url).send().await
151    }
152
153    /// Returns a list of bills that fit the candidate and category.
154    pub async fn get_bills_by_official_category_office(
155        &self,
156        candidate_id: i32,
157        category_id: i32,
158        office_id: Option<&str>,
159    ) -> Result<Response, Error> {
160        let url = format!(
161            "{base_url}{operation}?key={key}&candidateId={candidate_id}&categoryId={category_id}&officeId={office_id}&o=JSON",
162            base_url = &self.0.base_url,
163            key = &self.0.api_key,
164            operation = "Votes.getBillsByOfficialCategoryOffice",
165            candidate_id = candidate_id,
166            category_id = category_id,
167            office_id = office_id.unwrap_or("")
168        );
169
170        self.0.client.get(url).send().await
171    }
172
173    /// This method dumps all the bills an official has voted on based on the candidateId, officeId, categoryId, and year
174    pub async fn get_by_official(
175        &self,
176        candidate_id: i32,
177        office_id: Option<&str>,
178        category_id: Option<&str>,
179        year: Option<&str>,
180    ) -> Result<Response, Error> {
181        let url = format!(
182            "{base_url}{operation}?key={key}&candidateId={candidate_id}&categoryId={category_id}&officeId={office_id}&year={year}&o=JSON",
183            base_url = &self.0.base_url,
184            key = &self.0.api_key,
185            operation = "Votes.getByOfficial",
186            candidate_id = candidate_id,
187            category_id = category_id.unwrap_or(""),
188            office_id = office_id.unwrap_or(""),
189            year = year.unwrap_or("")
190        );
191
192        self.0.client.get(url).send().await
193    }
194
195    /// Returns a list of bills that fit the sponsor's candidateId and year.
196    pub async fn get_bills_by_sponsor_year(
197        &self,
198        candidate_id: i32,
199        year: i32,
200    ) -> Result<Response, Error> {
201        let url = format!(
202            "{base_url}{operation}?key={key}&candidateId={candidate_id}&year={year}&o=JSON",
203            base_url = &self.0.base_url,
204            key = &self.0.api_key,
205            operation = "Votes.getBillsBySponsorYear",
206            candidate_id = candidate_id,
207            year = year
208        );
209
210        self.0.client.get(url).send().await
211    }
212
213    /// Returns a list of bills that fit the sponsor's candidateId and category.
214    pub async fn get_bills_by_sponsor_category(
215        &self,
216        candidate_id: i32,
217        category_id: i32,
218    ) -> Result<Response, Error> {
219        let url = format!(
220            "{base_url}{operation}?key={key}&candidateId={candidate_id}&categoryId={category_id}&o=JSON",
221            base_url = &self.0.base_url,
222            key = &self.0.api_key,
223            operation = "Votes.getBillsBySponsorCategory",
224            candidate_id = candidate_id,
225            category_id = category_id
226        );
227
228        self.0.client.get(url).send().await
229    }
230
231    /// Returns a list of recent bills according to the state. Max returned is 100 or however much less you want.
232    pub async fn get_bills_by_state_recent(
233        &self,
234        state_id: String,
235        amount: Option<i32>,
236    ) -> Result<Response, Error> {
237        let url = format!(
238            "{base_url}{operation}?key={key}&state_id={state_id}&amount={amount}&o=JSON",
239            base_url = &self.0.base_url,
240            key = &self.0.api_key,
241            operation = "Votes.getBillsByStateRecent",
242            state_id = state_id,
243            amount = amount.unwrap_or(100)
244        );
245
246        self.0.client.get(url).send().await
247    }
248
249    /// Returns a list of vetoes according to candidate.
250    pub async fn get_vetoes(&self, candidate_id: i32) -> Result<Response, Error> {
251        let url = format!(
252            "{base_url}{operation}?key={key}&candidateId={candidate_id}&o=JSON",
253            base_url = &self.0.base_url,
254            key = &self.0.api_key,
255            operation = "Votes.getVetoes",
256            candidate_id = candidate_id
257        );
258
259        self.0.client.get(url).send().await
260    }
261}
262
263#[cfg(test)]
264mod tests {
265    use crate::VotesmartProxy;
266
267    #[tokio::test]
268    async fn test_get_categories() {
269        let proxy = VotesmartProxy::new().unwrap();
270        let response = proxy.votes().get_categories(2020, None).await.unwrap();
271        assert!(response.status().is_success());
272        let json: serde_json::Value = response.json().await.unwrap();
273        assert_eq!(json["categories"]["category"][0]["name"], "Abortion");
274    }
275
276    #[tokio::test]
277    async fn test_get_bill() {
278        let proxy = VotesmartProxy::new().unwrap();
279        let response = proxy.votes().get_bill(32020).await.unwrap();
280        assert!(response.status().is_success());
281        let json: serde_json::Value = response.json().await.unwrap();
282        assert_eq!(
283            json["bill"]["title"],
284            "Joint resolution relating to increasing the debt limit"
285        );
286    }
287
288    #[tokio::test]
289    async fn test_get_bill_action() {
290        let proxy = VotesmartProxy::new().unwrap();
291        let response = proxy.votes().get_bill_action(83811).await.unwrap();
292        assert!(response.status().is_success());
293        let json: serde_json::Value = response.json().await.unwrap();
294        assert_eq!(json["action"]["billId"], "32020");
295    }
296}