Include live weather from wttr.in (e.g. into travel notes)

Hey there,

I recently started to use Silverbullet to collect notes about an upcoming road trip. As we travel bigger distances with varying climate, I thought it’d be nice to have glimpse of the current weather conditions of up-coming destinations. So I hacked together the following snippet using space-script to retrieve data from the awesome wttr.in project. The snippet registers a function that consumes a location string (typically city name, see wttr.in docs for details) and outputs a single line weather output and a link to see more details. The weather information is stored in client store and only updated when older than an hour to avoid unnecessary loads and load faster.

Preview of the result

Usage example

```template
{{getWeather("Berlin")}}
```

Space Script

```space-script
const ONE_HOUR = 1000*3600;

silverbullet.registerFunction({name: "getWeather"}, async (location) => {
  // try to retrieve data from client store
  var weather = await clientStore.get(`weather_${location}`);

  // pull data if no weather info is available or older than an hour
  const timestamp = new Date().getTime();
  if (!weather || !weather.timestamp || weather.timestamp < timestamp-ONE_HOUR) {
    const wttrUrl = `https://wttr.in/${location}?format=%l:+%c+%t`;
    const response = await fetch(wttrUrl);

    if (response.ok) {
      const condition = await response.text();
      weather = {
        condition: condition,
        timestamp: timestamp,
      }
      clientStore.set(`weather_${location}`, weather);
    }
  }

  // when still no data is present, show an error message
  if (!weather) {
    return "❌ Not weather data available.";
  }

  return `${weather.condition} ([Forecast](https://wttr.in/${location}))`;
});
```

Limitation

The current example is quite limited as it only pulls the current condition instead of a proper forecast. This could probably be achived using the JSON Output of wttr. Maybe making the output more configurable. I am also not sure if the client store is the proper storage to cache the results, but it seems to work for me. So feel free to provide suggestions or ideas for improvement.

10 Likes

Very cool! I thought about doing this at some point as plug, but never got around to it. With space script these things are super easy to do.

1 Like

I get an unregistered syscall error for clientStore.get.

Yes, actually this shouldn’t work (or perhaps I slightly tweaked the way this worked on Edge ). It should probably use the datastore API instead:

```space-script
const ONE_HOUR = 1000*3600;

silverbullet.registerFunction({name: "getWeather"}, async (location) => {
  // try to retrieve data from client store
  var weather = await datastore.get(["weather", location]);

  // pull data if no weather info is available or older than an hour
  const timestamp = new Date().getTime();
  if (!weather || !weather.timestamp || weather.timestamp < timestamp-ONE_HOUR) {
    const wttrUrl = `https://wttr.in/${location}?format=%l:+%c+%t`;
    const response = await fetch(wttrUrl);

    if (response.ok) {
      const condition = await response.text();
      weather = {
        condition: condition,
        timestamp: timestamp,
      }
      clientStore.set(["weather", location], weather);
    }
  }

  // when still no data is present, show an error message
  if (!weather) {
    return "❌ Not weather data available.";
  }

  return `${weather.condition} ([Forecast](https://wttr.in/${location}))`;
});
```

Should work

1 Like

I also changed clientStore.set to datastore.set as well. It works now, thanks!

Yeah, the clientStore may be only available when using synced mode, so the data store is probably the better way :smile:.