Skip to content

Commit 205b257

Browse files
authored
Merge pull request #1011 from simao/weather-refactor
Refactored weather block to use curl crate
2 parents 7a71a37 + c0a0d3c commit 205b257

File tree

8 files changed

+388
-227
lines changed

8 files changed

+388
-227
lines changed

Cargo.lock

Lines changed: 89 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ serde_json = "1.0"
2929
swayipc = "2.7"
3030
toml = "0.5"
3131
signal-hook = "0.1.16"
32+
curl = "0.4"
3233

3334
# Optional features/blocks
3435
libpulse-binding = { optional = true, version = "2.15.0", default-features = false }

blocks.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,9 +1531,10 @@ Key | Values | Required | Default
15311531
`api_key` | Your OpenWeatherMap API key. | Yes | None
15321532
`city_id` | OpenWeatherMap's ID for the city. | Yes* | None
15331533
`place` | OpenWeatherMap 'By city name' search query. See [here](https://openweathermap.org/current) | Yes* | None
1534+
`coordinates` | GPS latitude longitude coordinates as a tuple, example: `["39.236229089090216","9.331730718685696"]`
15341535
`units` | Either `metric` or `imperial`. | Yes | `metric`
15351536

1536-
Either one of `city_id` or `place` is required. If both are supplied, `city_id` takes precedence.
1537+
One of `city_id`, `place` or `coordinates` is required. If more than one are supplied, `city_id` takes precedence over `place` which takes place over `coordinates`.
15371538

15381539
The options `api_key`, `city_id`, `place` can be omitted from configuration,
15391540
in which case they must be provided in the environment variables
@@ -1549,6 +1550,7 @@ Key | Value
15491550
`{humidity}` | Humidity
15501551
`{weather}` | Textual description of the weather, e.g. "Raining"
15511552
`{wind}` | Wind speed
1553+
`{wind_kmh}` | Wind speed. The wind speed in km/h.
15521554
`{direction}` | Wind direction, e.g. "NE"
15531555

15541556
###### [↥ back to top](#list-of-available-blocks)

src/blocks/docker.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::collections::BTreeMap;
2-
use std::process::Command;
32
use std::time::Duration;
43

54
use crossbeam_channel::Sender;
@@ -9,6 +8,7 @@ use crate::blocks::{Block, ConfigBlock, Update};
98
use crate::config::Config;
109
use crate::de::deserialize_duration;
1110
use crate::errors::*;
11+
use crate::http;
1212
use crate::input::I3BarEvent;
1313
use crate::scheduler::Task;
1414
use crate::util::{pseudo_uuid, FormatTemplate};
@@ -92,29 +92,15 @@ impl ConfigBlock for Docker {
9292

9393
impl Block for Docker {
9494
fn update(&mut self) -> Result<Option<Update>> {
95-
let output = match Command::new("sh")
96-
.args(&[
97-
"-c",
98-
"curl --fail --unix-socket /var/run/docker.sock http:/api/info",
99-
])
100-
.output()
101-
{
102-
Ok(raw_output) => {
103-
String::from_utf8(raw_output.stdout).block_error("docker", "Failed to decode")?
104-
}
105-
Err(_) => {
106-
// We don't want the bar to crash if we can't reach the docker daemon.
107-
self.text.set_text("N/A".to_string());
108-
return Ok(Some(self.update_interval.into()));
109-
}
110-
};
111-
112-
if output.is_empty() {
95+
let socket_path = std::path::PathBuf::from("/var/run/docker.sock");
96+
let output = http::http_get_socket_json(socket_path, "http:/api/info");
97+
98+
if output.is_err() {
11399
self.text.set_text("N/A".to_string());
114100
return Ok(Some(self.update_interval.into()));
115101
}
116102

117-
let status: Status = serde_json::from_str(&output)
103+
let status: Status = serde_json::from_value(output.unwrap().content)
118104
.block_error("docker", "Failed to parse JSON response.")?;
119105

120106
let values = map!(

src/blocks/github.rs

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::collections::{BTreeMap, HashMap};
2-
use std::process::Command;
32
use std::time::Duration;
43

54
use crossbeam_channel::Sender;
@@ -11,6 +10,7 @@ use crate::blocks::{Block, ConfigBlock, Update};
1110
use crate::config::Config;
1211
use crate::de::deserialize_duration;
1312
use crate::errors::*;
13+
use crate::http;
1414
use crate::input::I3BarEvent;
1515
use crate::scheduler::Task;
1616
use crate::util::{pseudo_uuid, FormatTemplate};
@@ -197,48 +197,25 @@ impl<'a> Notifications<'a> {
197197
return Ok(None);
198198
}
199199

200-
let result = Command::new("sh")
201-
.args(&[
202-
"-c",
203-
&format!(
204-
"curl --silent --dump-header - --header \"Authorization: Bearer {token}\" -m 3 \"{next_page_url}\"",
205-
token = self.token,
206-
next_page_url = self.next_page_url,
207-
),
208-
])
209-
.output()?;
210-
211-
// Catch all errors, if response status is not 200, then curl wont exit with status code 0.
212-
if !result.status.success() {
213-
return Err(Box::new(BlockError(
214-
"github".to_owned(),
215-
"curl status code different than 0".to_owned(),
216-
)));
217-
}
218-
219-
let output = String::from_utf8(result.stdout)?;
220-
221-
// Status / headers sections are separed by a blank line.
222-
let split: Vec<&str> = output.split("\r\n\r\n").collect();
223-
if split.len() != 2 {
224-
return Err(Box::new(BlockError(
225-
"github".to_owned(),
226-
"unexpected curl output".to_owned(),
227-
)));
228-
}
229-
230-
let (meta, body) = (split[0], split[1]);
231-
232-
let next = match meta.lines().find(|&l| l.starts_with("Link:")) {
233-
Some(v) => match parse_links_header(v).get("next") {
234-
Some(next) => next,
235-
None => "",
236-
},
237-
None => "",
238-
};
239-
self.next_page_url = next.to_owned();
200+
let header_value = format!("Bearer {}", self.token);
201+
let headers = vec![("Authorization", header_value.as_str())];
202+
let result =
203+
http::http_get_json(&self.next_page_url, Some(Duration::from_secs(3)), headers)?;
204+
205+
self.next_page_url = result
206+
.headers
207+
.iter()
208+
.find_map(|header| {
209+
if header.starts_with("Link:") {
210+
parse_links_header(header).get("next").cloned()
211+
} else {
212+
None
213+
}
214+
})
215+
.unwrap_or(&"")
216+
.to_string();
240217

241-
let notifications: Vec<Notification> = serde_json::from_str(body)?;
218+
let notifications: Vec<Notification> = serde_json::from_value(result.content)?;
242219
self.notifications = notifications.into_iter();
243220

244221
Ok(self.notifications.next())

0 commit comments

Comments
 (0)