Appearance
Generating events on the fly from a non-Nostr data-source
Suppose you want to serve events with the weather data for periods in the past. All you have is a big CSV file with the data.
Then you get a query like {"#g": ["d6nvp"], "since": 1664074800, "until": 1666666800, "kind": 10774}, imagine for a while that kind 10774 means weather data.
First you do some geohashing calculation to discover that d6nvp corresponds to Willemstad, Curaçao, then you query your XML file for the Curaçao weather data for the given period -- from 2022-09-25 to 2022-10-25, then you return the events corresponding to such query, signed on the fly:
go
func main () {
// other stuff here
relay := khatru.NewRelay()
relay.QueryStored = handleWeatherQuery
// other stuff here
}
func handleWeatherQuery(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] {
if filter.Kind != nostr.Kind(10774) {
// this function only handles kind 10774, if the query is for something else we return
// a nil channel, which corresponds to no results
return nil
}
file, err := os.Open("weatherdata.xml")
if err != nil {
return nil
}
return func(yield func(nostr.Event) bool) {
defer file.Close()
// we're going to do this for each tag in the filter
gTags, _ := filter.Tags["g"]
for _, gTag := range gTags {
// translate geohash into city name
citName, err := geohashToCityName(gTag)
if err != nil {
continue
}
reader := csv.NewReader(file)
for {
record, err := reader.Read()
if err != nil {
return
}
// ensure we're only getting records for Willemstad
if cityName != record[0] {
continue
}
date, _ := time.Parse("2006-01-02", record[1])
ts := nostr.Timestamp(date.Unix())
if ts > filter.Since && ts < filter.Until {
// we found a record that matches the filter, so we make
// an event on the fly and return it
evt := nostr.Event{
CreatedAt: ts,
Kind: 10774,
Tags: nostr.Tags{
{"temperature", record[2]},
{"condition", record[3]},
}
}
evt.Sign(global.RelaySecretKey)
if !yield(evt) {
return
}
}
}
}
}()
}
}Beware, the code above is inefficient and the entire approach is not very smart, it's meant just as an example.
