This package is now actively maintained by GetStream.
stream-go is a (beta) Go client for Stream.
You can sign up for a Stream account at https://getstream.io/get_started.
This library could not exist without the efforts of several open-source community members, including the awesome folks at MrHenry and HyperWorks. Thank you so much for contributing to our community!
The code provided by the MrHenry team is used with written permission; we are working with them to get a final license in place. Stream will be modifying the codebase together with MrHenry over time, so we especially want to point out how great they have been working with us to release this library.
We are releasing this as our v0.9.0 beta since there may be bugs, and inevitable cleanup will happen along the way. Please do not hesitate to contact us if you see something strange happening. We'd be happy to consider any and all pull requests from the community as well!
- Improved test coverage (currently around 84%)
- Refactoring to make some methods and attributes private which don't need exposure
- Ensuring Go best practices
Documentation for this Go client are available at the Stream website.
Creating a client:
import (
"fmt"
"github.com/GetStream/stream-go"
)
// we recommend getting your API credentials using os.Getenv()
client, err := getstream.New(&getstream.Config{
APIKey: os.Getenv("STREAM_API_KEY"),
APISecret: os.Getenv("STREAM_API_SECRET"),
AppID: os.Getenv("STREAM_APP_ID"),
Location: os.Getenv("STREAM_REGION"),
TimeoutInt: os.Getenv("STREAM_TIMEOUT"),
})
if err != nil {
return err
}
// but you can define the variables in code as well, of course
APIKey string = "your-api-key"
APISecret string = "your-api-secret"
// your application ID, found on your GetStream.io dashboard
AppID string = "16013"
// Location is optional; leaving it blank will default the
// hostname to "api.getstream.io"
// but we do have geographic-specific choices:
// "us-east", "us-west" and "eu-west"
Location string = "us-east"
// TimeoutInt is an optional integer parameter to define
// the number of seconds before your connection will hang-up
// during a request; you can set this to any non-negative
// and non-zero whole number, and will default to 3
TimeoutInt: 3
client, err := getstream.New(&getstream.Config{
APIKey: APIKey,
APISecret: APISecret,
AppID: AppID,
Location: Location,
TimeoutInt: TimeoutInt,
})
Creating a Feed object for a user:
// this code assumes you've created a flat feed named "flat-feed-name" for your app
// and similarly-named feeds for aggregated feeds and notification feeds
// we also recommend using UUID values for users
bobFlatFeed, err := client.FlatFeed("flat-feed-name", "bob-uuid")
if err != nil {
return err
}
bobAggregatedFeed, err := client.AggregatedFeed("aggregated-feed-name", "bob-uuid")
if err != nil {
return err
}
bobNotificationFeed, err := client.NotificationFeed("notification-feed-name", "bob-uuid")
if err != nil {
return err
}
Creating an activity on Bob's flat feed:
import "github.com/pborman/uuid"
activity, err := bobFeed.AddActivity(&Activity{
Verb: "post",
ForeignID: uuid.New(),
Object: "flat:eric",
Actor: "flat:john",
})
if err != nil {
return err
}
The library is gradually introducing JWT support. You can generate a client token for a feed using the following example:
// create a client using your API key and secret
client, err := getstream.New(&getstream.Config{
APIKey: os.Getenv("STREAM_API_KEY"),
APISecret: os.Getenv("STREAM_API_SECRET"),
AppID: os.Getenv("STREAM_APP_ID"),
Location: os.Getenv("STREAM_REGION"),
})
// create a feed
feed, err := client.FlatFeed("flat-feed-name", "bob-uuid")
if err != nil {
return err
}
// create a JWT token for the feed
token, err := client.Signer.GenerateFeedScopeToken(
getstream.ScopeContextFeed,
getstream.ScopeActionRead,
bobFeed)
if err != nil {
fmt.Println(err)
}
// create a new client using the token
// note in the struct below that we're not setting "APISecret"
// but setting "Token" instead:
bobFlatFeedJWTClient, err := getstream.NewWithToken(&getstream.Config{
APIKey: os.Getenv("STREAM_API_KEY"),
Token: token, // not setting APISecret
AppID: os.Getenv("STREAM_APP_ID"),
Location: os.Getenv("STREAM_REGION"),
})
if err != nil {
return err
}
JWT support is not yet fully tested on the library, but we'd love to hear any feedback you have as you try it out.
Flat Feed
- Add one or more Activities (AddActivity, AddActivities)
- Remove Activity (RemoveActivity, RemoveActivityByForeignID)
- Get a list of Activities on the Feed (Activities)
- Follow another Feed (FollowFeedWithCopyLimit)
- UnFollow another Feed (Unfollow, UnfollowAggregated, UnfollowNotification, UnfollowKeepingHistory)
- Get Followers of this Feed (FollowersWithLimitAndSkip)
- Get list of Feeds this Feed is Following (FollowingWithLimitAndSkip)
- Follow Many Feeds (FollowManyFeeds)
- Update one or more Activities (UpdateActivity, UpdateActivities)
Aggregated Feed
- Add one or more Activities (AddActivity, AddActivities)
- Remove Activity (RemoveActivity, RemoveActivityByForeignID)
- Get a list of Activities on the Feed (Activities)
- Follow another Feed (FollowFeedWithCopyLimit)
- UnFollow another Feed (Unfollow, UnfollowKeepingHistory)
- Get Followers of this Feed (FollowersWithLimitAndSkip)
- Get list of Feeds this Feed is Following (FollowingWithLimitAndSkip)
Notification Feed
- Add one or more Activities (AddActivity, AddActivities)
- Remove Activity (RemoveActivity, RemoveActivityByForeignID)
- Get a list of Activities on the Feed (Activities)
- Follow another Feed (FollowFeedWithCopyLimit)
- UnFollow another Feed (Unfollow, UnfollowKeepingHistory)
- Get list of Feeds this Feed is Following (FollowingWithLimitAndSkip)
- Mark Read (MarkActivitiesAsRead)
- Mark Seen (MarkActivitiesAsSeenWithLimit)
- Get Followers of this Feed (FollowersWithLimitAndSkip)
Payload building Follows our API standards for all request payloads
data
: Statically typed payloads asjson.RawMessage
metadata
: Top-level key/value pairs
You can/should use data
to send Go structures through the library. This
will give you the benefit of Go's static type system. If you are unable
to determine a type (or compatible type) for the contents of an Activity,
you can use metadata
which is a map[string]string
; encoding this to
JSON will move these values to the top-level, so any keys you define in
your metadata
which conflict with our standard top-level keys will be
overwritten.
The benefit of this metadata
structure is that these key/value pairs
will be exposed to Stream's internals such as ranking.
Many design choices in the library were inherited from the team at MrHenry, with some choices to refactor some of the test code as its own getstream_test package. This choice meant exposing some attributes that perhaps should be left private, and we expect this re-refactoring will take place over time.
The MrHenry team noted this about the Flat / Aggregated / Notification Feed types:
- they have separate structures and methods to prevent the impact of future Stream changes
- if two types of feeds grow farther apart, incorporated future changes in this client should not breaking everything
Have we mentioned the team at MrHenry yet??
This pkg started out as a fork from HyperWorks and still borrows snippets (token & errors) from the original. We decided to make this a separate repo entirely because drastic changes were made to the interface and internal workings.
We received great support from Stream while creating this pkg for which we are very grateful, and we also want to thank them for creating Stream in the first place.