radarapi

package module
v0.0.0-...-50fac79 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 27, 2019 License: GPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package radarapi provides bindings for the radar.squat.net event API.

A very brief documention of the API can be found at https://radar.squat.net/en/api

This document will give a more detailed description and provide examples for both the web api and the go bindings found in this package.

General

The radar database consists of the following entities:

  • events : any kind of event, e.g. a party, workshop, etc.
  • groups : a group organizes events. Some groups just act as promoters and add events to the database without actually organzing them, e.g. "Stressfaktor". An event can be linked to multiple groups.
  • location : a place where an event happens.
  • taxonomy term : a category for events, groups and locations, e.g. "party", "workshop", "bar/cafe", etc. Any of the above entities can be linked to multiple taxonomy terms.

Each entity comes with a set of fields. The list of available fields for each entity can be found in the corresponding subpackages (see subdirectories). All entities have a common field UUID which uniquely identifies an entity instance.

Endpoints

The rest API provides endpoints for each of those entities:

event: https://radar.squat.net/api/1.2/node/[uuid].json
file:  https://radar.squat.net/api/1.2/file/[uuid].json
group: https://radar.squat.net/api/1.2/node/[uuid].json
location: https://radar.squat.net/api/1.2/location/[uuid].json
term: https://radar.squat.net/api/1.2/taxonomy_term/[uuid].json

Entity parameters

The entity endpoints support two parameters:

  • fields: the fields to be returned.
  • language: use the specified language, if available.

By default, all available fields for an entity are returned. Alternatively, a comma-separated list of fields can be passed:

https://radar.squat.net/api/1.2/node/[uuid].json?fields=field1,field2,field3

The default language is english (or UND???). To change the language pass an ISO language code like this:

https://radar.squat.net/api/1.2/node/[uuid].json?language=de

The corresponding go bindings for these endpoints provided by this package are named Event(), Group(), Location() and Term() and can be found below.

Search Endpoints

The API supports searching the database for entities through the following endpoints:

event: https://radar.squat.net/api/1.2/search/events.json
group: https://radar.squat.net/api/1.2/search/groups.json
location: https://radar.squat.net/api/1.2/search/location.json
term: https://radar.squat.net/api/1.2/search/term.json

Without any parameters, events will return all events with an end time greater than (now - 2h). group, location and term will simply return all.

In most cases you'd only want a subset of the data, therefore the API provides different means of filtering the results. See Facet and Filter below for info and examples on how to filter the results.

Apart from facets and filters, the search API supports the following other parameters:

  • keys: string used for full-text search.
  • fields: see Entity Parameters above, with the extension that reference fields can be auto resolved (see ResolveField below).
  • language: see Entity Parameters above.
  • limit: return at most n results, see Limit() below.
  • sort: sorts the results by the specified field in the given order (asc or desc), see Sort() below.

Searching with this library is done via the SearchBuilder type (see below for a description and examples).

Index

Examples

Constants

View Source
const (
	OperatorAnd   = "~and"
	OperatorOR    = "~or"
	ComparatorEQ  = "~e"
	ComparatorNEQ = "~ne"
	ComparatorGT  = "~gt"
	ComparatorGTE = "~gte"
	ComparatorLT  = "~lt"
	ComparatorLTE = "~lte"
)
View Source
const (
	// Start date and time of an event, unix timestamp
	FilterEventStartDateTime = "search_api_aggregation_1"
	// End date and time of an event, unix timestamp
	FilterEventEndDateTime = "search_api_aggregation_3"
	// City an event is taking place at.
	FilterEventLocation = "field_offline:field_address:locality"
)

Variables

This section is empty.

Functions

func ResolveField

func ResolveField(reference string, target string, targetN ...string) string

When searching for an entity, the result may contain a field which is a reference to another entity. Normally, one would have to do another API call to fetch this referenced entity. The radar api, however, allows us to specify fields which should be resolved automatically.

In the radar rest api this is done like this

fields=referenceField:targetField

or even

fields=referenceField:anotherReference:targetField

The Go equivalent is using this method

ResolveField(referenceField, targetField)

or

ResolveField(referenceField, anotherReference, targetField)

The arguments can be any of the event/group/location/term FieldXXXs

Example

Search result for events showing the title and the field 'offline', which is a reference to the location entity.

Using the radar rest api

https://radar.squat.net/api/1.2/search/events.json?fields=title,offline

In Go

radar := NewRadarClient()
sb := NewSearch(typeEvent)
sb.Fields(event.FieldTitle, event.FieldOffline)
raw, err := radar.Search(sb)

Result

"346823": {
    "offline": [
      {
        "uri": "https://radar.squat.net/api/1.2/location/8b8b63b2-64e5-4831-a91d-7f77bb510890",
        "id": "8b8b63b2-64e5-4831-a91d-7f77bb510890",
        "resource": "location",
        "title": "K19 Café Kreutzigerstr. 19  Berlin Deutschland"
      }
    ],
    "title": "CryptoParty"
  }

Clicking the uri will reveal the following structure of the location entity:

{
 "address": {
   "country": "DE",
   "name_line": "K19 Café",
   "first_name": "K19",
   "last_name": "Café",
   "organisation_name": null,
   "administrative_area": null,
   "sub_administrative_area": null,
   "locality": "Berlin",
   "dependent_locality": null,
   "postal_code": "10247",
   "thoroughfare": "Kreutzigerstr. 19",
   "premise": ""
 },
 "directions": "U-Bhf. Samariterstrasse",
 "map": {
   "geom": "POINT (13.4600646 52.5131015)",
   "geo_type": "point",
   "lat": "52.513101500000",
   "lon": "13.460064600000",
   "left": "13.460064600000",
   "top": "52.513101500000",
   "right": "13.460064600000",
   "bottom": "52.513101500000",
   "srid": null,
   "latlon": "52.513101500000,13.460064600000",
   "schemaorg_shape": ""
 },
 "timezone": "Europe/Berlin",
 "squat": null,
 "id": "225",
 "type": "location",
 "title": "K19 Café Kreutzigerstr. 19  Berlin Deutschland",
 "uuid": "8b8b63b2-64e5-4831-a91d-7f77bb510890",
 "feed_nid": null
}

We can now resolve the address Field (or any of the others) like this

https://radar.squat.net/api/1.2/search/events.json?fields=title,offline,offline:address

In Go

radar := NewRadarClient()
sb := NewSearch(typeEvent)
sb.Fields(event.FieldTitle, event.FieldOffline, ResolveField(event.Offline, location.Address))
raw, err := radar.Search(sb)

Result

"346823": {
    "offline": [
      {
        "uri": "https://radar.squat.net/api/1.2/location/8b8b63b2-64e5-4831-a91d-7f77bb510890",
        "id": "8b8b63b2-64e5-4831-a91d-7f77bb510890",
        "resource": "location",
        "title": "K19 Café Kreutzigerstr. 19  Berlin Deutschland",
        "address": {
          "country": "DE",
          "name_line": "K19 Café",
          "first_name": "K19",
          "last_name": "Café",
          "organisation_name": null,
          "administrative_area": null,
          "sub_administrative_area": null,
          "locality": "Berlin",
          "dependent_locality": null,
          "postal_code": "10247",
          "thoroughfare": "Kreutzigerstr. 19",
          "premise": ""
        }
      }
    ],
    "title": "CryptoParty"
  }
Example

Get all events in Berlin and include the address field of the locations.

// https://radar.squat.net/api/1.2/search/events.json?facets[city][]=Berlin&fields=title,offline,offline:address
radar := NewRadarClient()
sb := &SearchBuilder{}
sb.Facets(Facet{event.FacetCity, "Berlin"})
sb.Fields(event.FieldTitle, event.FieldOffline, ResolveField(event.FieldOffline, location.FieldAddress))
result, err := radar.SearchEvents(sb)
if err != nil {
	fmt.Printf("%v", err)
	return
}
if result == nil {
	fmt.Println("No results")
}
fmt.Printf("%v", result)
Output:

Types

type Facet

type Facet struct {
	// One of event/group/location/term FacetXXXs. Must match the entity you are searching for,
	// e.g. when searching for an Event it must be from event.FacetXXXX
	Key   string
	Value string
}

Facets provide an easy way to filter results by entity properties.

For each entity there's a predefined set of facets. The list of available facets can be found in the corresponding subpackages (see subdirectories).

Facets can be passed to the server by using the facets parameter:

https://radar.squat.net/api/1.2/search/events.json?facets[facet][]=value

Example

https://radar.squat.net/api/1.2/search/events.json?facets[city][]=Berlin

Multiple facets can be passed, even the same with different values. When passing the same facet with different values the logical operation (AND, OR) depends on the actual facet. Each facet is annotated with its operator (see Constants in the corresponding subpackages)

Example

category operator is AND, this call returns events which have both the bar/cafe AND theater category
https://radar.squat.net/api/1.2/search/events.json?facets[category][]=bar-cafe&facets[category][]=theater
group operator is OR, this call returns events organized by group 339006 OR 1599
https://radar.squat.net/api/1.2/search/events.json?facets[group][]=339006&fields=*&facets[group][]=1599
Example

Get all events in Berlin with the category work-space/diy happening on the 2020-11-24

radar := NewRadarClient()
sb := &SearchBuilder{}
sb.Facets(
	Facet{event.FacetCity, "Berlin"},
	Facet{event.FacetCategory, "work-space-diy"},
	Facet{event.FacetDate, "2020-11-24"})
result, err := radar.SearchEvents(sb)
if err != nil {
	fmt.Printf("%v", err)
	return
}
if result == nil {
	fmt.Println("No results")
}
fmt.Printf("%v", result)
Output:

type Filter

type Filter interface{}

Filters provide a somewhat more complex way to filter results.

Note: filtering only works on indexed fields.

Filters can be passed to the server by using the filter parameter:

https://radar.squat.net/api/1.2/search/events.json?filter[~operator][field][~comparator]=value

Possible operators are

  • ~and: all filters with ~and must evaluate to true
  • ~or: at least one of the ~or filters must evaluate to true

Comparators:

  • ~e: equals
  • ~ne: not equal
  • ~gt: greater than
  • ~gte: greater or equal than
  • ~lt: less than
  • ~lte: less or equal than

Note: filtering also works on resolved fields (see ResolveField).

Example

Get all events in Berlin
https://radar.squat.net/api/1.2/search/events.json?filter[~and][field_offline:field_address:locality][~eq]=Berlin

Note: most of the equal filters, like in this example, can be be done with Facets in a simpler manner (see Facets).

One of the more interesting things you can do is filtering for a time period

Get all events in Berlin with a start date between 2020-11-03 00:00:00 and 2020-11-25 00:00:00
https://radar.squat.net/api/1.2/search/events.json?facets[city][]=Berlin&filter[~and][search_api_aggregation_1][~gt]=1604358000&filter[~or][search_api_aggregation_1][~lt]=1606258800

In Go filters can be created with CreateFilter() and CreateRangeFilter().

There are some predefined constants which can be used as fields when filtering (FilterXXX), see constants above.

Limitations

Filters can't be grouped, i.e. things like

(cond1 AND cond2) OR cond3

are not possible.

A field can't be used in more than one equals filter, i.e. you can't filter for events in Berlin OR Amsterdam because that would require using the field locality twice.

filter[~and][field_offline:field_address:locality][~eq]=Berlin&filter[~or][field_offline:field_address:locality][~eq]=Amsterdam

func CreateFilter

func CreateFilter(operator string, field string, comparator string, value string) Filter

Creates a filter which can be passed to SearchBuilder.Filters().

See type Filter for a detailed description.

Example

Get all events in Berlin which are not organized/promoted by group "Stressfaktor" (id: 1599)

// https://radar.squat.net/api/1.2/search/events.json?facets[city][]=Berlin&filter[~and][og_group_ref][~ne]=1599
radar := NewRadarClient()
sb := &SearchBuilder{}
sb.Facets(Facet{event.FacetCity, "Berlin"})
sb.Filters(CreateFilter(OperatorAnd, event.FieldOgGroupRef, ComparatorNEQ, "1599"))
result, err := radar.SearchEvents(sb)
if err != nil {
	fmt.Printf("%v", err)
	return
}
if result == nil {
	fmt.Println("No results")
}
fmt.Printf("%v", result)
Output:

func CreaterRangeFilter

func CreaterRangeFilter(field string, from string, to string) Filter

Creates a range filter which can be passed to SearchBuilder.Filters().

See type Filter for a detailed description.

Example

Get all events in Berlin with a start date between 2020-11-03 00:00:00 and 2020-11-25 00:00:00

//  https://radar.squat.net/api/1.2/search/events.json?facets[city][]=Berlin&filter[~and][search_api_aggregation_1][~gt]=1604358000&filter[~or][search_api_aggregation_1][~lt]=1606258800
radar := NewRadarClient()
sb := &SearchBuilder{}
sb.Facets(Facet{event.FacetCity, "Berlin"})
sb.Filters(CreaterRangeFilter(FilterEventStartDateTime, "1604358000", "1606258800"))
result, err := radar.SearchEvents(sb)
if err != nil {
	fmt.Printf("%v", err)
	return
}
if result == nil {
	fmt.Println("No results")
}
fmt.Printf("%v", result)
Output:

type RadarClient

type RadarClient struct {
	// contains filtered or unexported fields
}

func NewRadarClient

func NewRadarClient() *RadarClient

Returns an instance of RadarClient which can be used to interact with the radar server.

func (*RadarClient) Event

func (radar *RadarClient) Event(uuid string, language *lang.Tag, fields ...string) (*event.Event, error)

Get the Event associated with uuid. If no fields are specified the default are returned.

Example

Get event "e81b15f9-663f-4270-b94b-269176cd9f3f".

// https://radar.squat.net/api/1.2/node/e81b15f9-663f-4270-b94b-269176cd9f3f.json
radar := NewRadarClient()
result, err := radar.Event("e81b15f9-663f-4270-b94b-269176cd9f3f", nil)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("%v", result.Title)
Output:

Seawatch Soli Fete Tag 1
Example (Fields)

Get event "e81b15f9-663f-4270-b94b-269176cd9f3f" with fields title and event status.

// https://radar.squat.net/api/1.2/node/e81b15f9-663f-4270-b94b-269176cd9f3f.json?fields=title,event_status
radar := NewRadarClient()
result, err := radar.Event("e81b15f9-663f-4270-b94b-269176cd9f3f", nil, event.FieldTitle, event.FieldEventStatus)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("title: %s, status: %s", result.Title, result.EventStatus)
Output:

title: Seawatch Soli Fete Tag 1, status: confirmed

func (*RadarClient) File

func (radar *RadarClient) File(uuid string, language *lang.Tag, fields ...string) (*file.File, error)

Get the File associated with uuid. If no fields are specified the default are returned.

func (*RadarClient) Group

func (radar *RadarClient) Group(uuid string, language *lang.Tag, fields ...string) (*group.Group, error)

Get the Group associated with uuid. If no fields are specified the default are returned.

Example

Get group "Liebig34" : "7a8de6aa-5951-467f-a4a4-1d558eea5d3c" and print title and description.

// https://radar.squat.net/api/1.2/node/7a8de6aa-5951-467f-a4a4-1d558eea5d3c.json
radar := NewRadarClient()
result, err := radar.Group("7a8de6aa-5951-467f-a4a4-1d558eea5d3c", nil)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("title: %s, description: %s", result.Title, result.Body.Value)
Output:

title: Liebig34, description: <p>Anarcha-Queer-Feminist houseproject in Berlin-Friedrichshain.</p>
<p>Non-smoking bar.</p>
<p> </p>

func (*RadarClient) Location

func (radar *RadarClient) Location(uuid string, language *lang.Tag, fields ...string) (*location.Location, error)

Get the Location associated with uuid. If no fields are specified the default are returned.

Example

Get location "2130ff33-8af2-4c76-a693-75d3b978a2aa" and print name and street.

// https://radar.squat.net/api/1.2/location/2130ff33-8af2-4c76-a693-75d3b978a2aa.json
radar := NewRadarClient()
result, err := radar.Location("2130ff33-8af2-4c76-a693-75d3b978a2aa", nil)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("name: %s, street: %s", result.Address.NameLine, result.Address.Thoroughfare)
Output:

name: Mensch Meier, street: Storkower Str. 121

func (*RadarClient) SearchEvents

func (radar *RadarClient) SearchEvents(sb *SearchBuilder) (*SearchResultEvents, error)

Search the radar database for Events. Returns nil if no results were found.

func (*RadarClient) SearchGroup

func (radar *RadarClient) SearchGroup(sb *SearchBuilder) (*SearchResultGroups, error)

Search the radar database for Groups. Returns nil if no results were found.

func (*RadarClient) SearchLocation

func (radar *RadarClient) SearchLocation(sb *SearchBuilder) (*SearchResultLocations, error)

Search the radar database for Locations. Returns nil if no results were found.

Note: By default, no fields are returned for the locations. Use SearchBuilder.Fields() to get a meaningful response.

func (*RadarClient) SearchTerm

func (radar *RadarClient) SearchTerm(sb *SearchBuilder) (*SearchResultTerms, error)

Search the radar database for Terms. Returns nil if no result were found.

func (*RadarClient) Term

func (radar *RadarClient) Term(uuid string, language *lang.Tag, fields ...string) (*term.Term, error)

Get the Term associated with uuid. If no fields are specified the default are returned.

Example

Get taxonomy term "2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8" and print name and description.

// https://radar.squat.net/api/1.2/taxonomy_term/2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8.json
radar := NewRadarClient()
result, err := radar.Term("2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8", nil)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("name: %s, description: %s", result.Name, result.Description)
Output:

name: bar/cafe, description: <p>somewhere were you can go for a drink and to meet people</p>
Example (Spanish)

Get taxonomy term "2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8" and print name and description in spanish.

// https://radar.squat.net/api/1.2/taxonomy_term/2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8.json?language=es
radar := NewRadarClient()
result, err := radar.Term("2a56c4d7-eb98-4f96-9ac6-d383a1af5ce8", &language.Spanish)
if err != nil {
	fmt.Printf("error: %v", err)
	return
}
fmt.Printf("name: %s, description: %s", result.Name, result.Description)
Output:

name: bar/café, description: <p>para tomarse una copita, conocer gente maja...</p>

type ResultFacet

type ResultFacet struct {
	Filter    string `json:"filter"`
	Count     int64  `json:"count"`
	Formatted string `json:"formatted"`
}

The response to a search request will return a list of available facets.

func (*ResultFacet) UnmarshalJSON

func (e *ResultFacet) UnmarshalJSON(data []byte) error

type SearchBuilder

type SearchBuilder struct {
	// contains filtered or unexported fields
}

A SearchBuilder is used to create a search request which can be passed to RadarClient.Search().

The zero value is ready to use.

func (*SearchBuilder) Facets

func (sb *SearchBuilder) Facets(facets ...Facet)

Sets the facets which will be used to filter the results. See Facet above.

func (*SearchBuilder) Fields

func (sb *SearchBuilder) Fields(fields ...string)

Sets the fields which will be returned for each result.

Fields must come from the entity you are searching for, e.g. for Event event.FieldXXXX. See subpackages for the available fields for each entity.

func (*SearchBuilder) Filters

func (sb *SearchBuilder) Filters(filters ...Filter)

Sets the filters which will be used to filter the results. See Filter above.

func (*SearchBuilder) Key

func (sb *SearchBuilder) Key(key string)

Sets a key for full-text search.

func (*SearchBuilder) Language

func (sb *SearchBuilder) Language(language lang.Tag)

Sets the language for the response.

func (*SearchBuilder) Limit

func (sb *SearchBuilder) Limit(limit uint16)

Sets the amount of results returned.

Must be 0 <= limit <= 500

func (*SearchBuilder) Sort

func (sb *SearchBuilder) Sort(field string, descending bool)

Sets the field used to sort the results.

Only works for indexed fields.

type SearchResultEvents

type SearchResultEvents struct {
	Results map[string]*event.Event `json:"result"`
	// Number of results. Only the first 500 are actually returned.
	Count  int64                     `json:"count"`
	Facets map[string][]*ResultFacet `json:"facets"`
}

type SearchResultGroups

type SearchResultGroups struct {
	Results map[string]*group.Group `json:"result"`
	// Number of results. Only the first 500 are actually returned.
	Count  int64                     `json:"count"`
	Facets map[string][]*ResultFacet `json:"facets"`
}

type SearchResultLocations

type SearchResultLocations struct {
	Results map[string]*location.Location `json:"result,omitempty"`
	// Number of results. Only the first 500 are actually returned.
	Count  int64                     `json:"count,string"`
	Facets map[string][]*ResultFacet `json:"facets"`
}

type SearchResultTerms

type SearchResultTerms struct {
	Results map[string]*term.Term `json:"result"`
	// Number of results. Only the first 500 are actually returned.
	Count  int64                     `json:"count"`
	Facets map[string][]*ResultFacet `json:"facets"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL