Skip to content

Commit

Permalink
Merge 78cf086 into 61fc56d
Browse files Browse the repository at this point in the history
  • Loading branch information
WillSewell committed Feb 4, 2021
2 parents 61fc56d + 78cf086 commit 3838ff8
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 121 deletions.
225 changes: 169 additions & 56 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,59 @@ be marshallable into JSON.
*/
func (c *Client) Trigger(channel string, eventName string, data interface{}) error {
return c.trigger([]string{channel}, eventName, data, nil)
_, err := c.trigger([]string{channel}, eventName, data, TriggerParams{})
return err
}

/*
ChannelsParams are any parameters than can be sent with a
TriggerWithParams or TriggerMultiWithParams requests.
*/
type TriggerParams struct {
// SocketID excludes a recipient whose connection has the `socket_id`
// specified here. You can read more here:
// http://pusher.com/docs/duplicates.
SocketID *string
// Info is comma-separated vales of `"user_count"`, for
// presence-channels, and `"subscription_count"`, for all-channels.
// Note that the subscription count is not allowed by default. Please
// contact us at http://support.pusher.com if you wish to enable this.
// Pass in `nil` if you do not wish to specify any query attributes.
Info *string
}

func (parameters TriggerParams) toMap() map[string]string {
m := make(map[string]string)
if parameters.SocketID != nil {
m["socket_id"] = *parameters.SocketID
}
if parameters.Info != nil {
m["info"] = *parameters.Info
}
return m
}

/*
TriggerWithParams is the same as `client.Trigger`, except it allows additional
parameters to be passed in. See:
https://pusher.com/docs/channels/library_auth_reference/rest-api#request
for a complete list.
data := map[string]string{"hello": "world"}
socketID := "1234.12"
attributes := "user_count"
parameters := TriggerParams{SocketID: &socketID, Info: &attributes}
channels, err := client.Trigger("greeting_channel", "say_hello", data, parameters)
//channels=> &{Channels:map[presence-chatroom:{UserCount:4} presence-notifications:{UserCount:31}]}
*/
func (c *Client) TriggerWithParams(
channel string,
eventName string,
data interface{},
parameters TriggerParams,
) (*TriggerChannelsList, error) {
return c.trigger([]string{channel}, eventName, data, parameters)
}

/*
Expand All @@ -152,35 +204,58 @@ TriggerMulti is the same as `client.Trigger`, except one passes in a slice of
client.TriggerMulti([]string{"a_channel", "another_channel"}, "event", data)
*/
func (c *Client) TriggerMulti(channels []string, eventName string, data interface{}) error {
return c.trigger(channels, eventName, data, nil)
_, err := c.trigger(channels, eventName, data, TriggerParams{})
return err
}

/*
TriggerMultiWithParams is the same as `client.TriggerMulti`, except it
allows additional parameters to be specified in the same way as
`client.TriggerWithParams`.
*/
func (c *Client) TriggerMultiWithParams(
channels []string,
eventName string,
data interface{},
parameters TriggerParams,
) (*TriggerChannelsList, error) {
return c.trigger(channels, eventName, data, parameters)
}

/*
TriggerExclusive triggers an event excluding a recipient whose connection has
the `socket_id` you specify here from receiving the event.
You can read more here: http://pusher.com/docs/duplicates.
client.TriggerExclusive("a_channel", "event", data, "123.12")
Deprecated: use TriggerWithParams instead.
*/
func (c *Client) TriggerExclusive(channel string, eventName string, data interface{}, socketID string) error {
return c.trigger([]string{channel}, eventName, data, &socketID)
parameters := TriggerParams{SocketID: &socketID}
_, err := c.trigger([]string{channel}, eventName, data, parameters)
return err
}

/*
TriggerMultiExclusive triggers an event to multiple channels excluding a
recipient whose connection has the `socket_id` you specify here from receiving
the event on any of the channels.
client.TriggerMultiExclusive([]string{"a_channel", "another_channel"}, "event", data, "123.12")
Deprecated: use TriggerMultiWithParams instead.
*/
func (c *Client) TriggerMultiExclusive(channels []string, eventName string, data interface{}, socketID string) error {
return c.trigger(channels, eventName, data, &socketID)
parameters := TriggerParams{SocketID: &socketID}
_, err := c.trigger(channels, eventName, data, parameters)
return err
}

func (c *Client) trigger(channels []string, eventName string, data interface{}, socketID *string) error {
func (c *Client) trigger(channels []string, eventName string, data interface{}, parameters TriggerParams) (*TriggerChannelsList, error) {
if len(channels) > maxTriggerableChannels {
return fmt.Errorf("You cannot trigger on more than %d channels at once", maxTriggerableChannels)
return nil, fmt.Errorf("You cannot trigger on more than %d channels at once", maxTriggerableChannels)
}
if !channelsAreValid(channels) {
return errors.New("At least one of your channels' names are invalid")
return nil, errors.New("At least one of your channels' names are invalid")
}

hasEncryptedChannel := false
Expand All @@ -191,28 +266,31 @@ func (c *Client) trigger(channels []string, eventName string, data interface{},
}
if hasEncryptedChannel && len(channels) > 1 {
// For rationale, see limitations of end-to-end encryption in the README
return errors.New("You cannot trigger to multiple channels when using encrypted channels")
return nil, errors.New("You cannot trigger to multiple channels when using encrypted channels")
}
masterKey, keyErr := c.encryptionMasterKey()
if hasEncryptedChannel && keyErr != nil {
return keyErr
return nil, keyErr
}
if err := validateSocketID(socketID); err != nil {
return err
if err := validateSocketID(parameters.SocketID); err != nil {
return nil, err
}

payload, err := encodeTriggerBody(channels, eventName, data, socketID, masterKey, c.OverrideMaxMessagePayloadKB)
payload, err := encodeTriggerBody(channels, eventName, data, parameters.toMap(), masterKey, c.OverrideMaxMessagePayloadKB)
if err != nil {
return err
return nil, err
}
path := fmt.Sprintf("/apps/%s/events", c.AppID)
triggerURL, err := createRequestURL("POST", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, payload, nil, c.Cluster)
if err != nil {
return err
return nil, err
}
response, err := c.request("POST", triggerURL, payload)
if err != nil {
return nil, err
}
_, err = c.request("POST", triggerURL, payload)

return err
return unmarshalledTriggerChannelsList(response)
}

/*
Expand All @@ -223,67 +301,91 @@ type Event struct {
Name string
Data interface{}
SocketID *string
Info *string
}

/*
TriggerBatch triggers multiple events on multiple channels in a single call:
client.TriggerBatch([]pusher.Event{
{ Channel: "donut-1", Name: "ev1", Data: "d1" },
{ Channel: "private-encrypted-secretdonut", Name: "ev2", Data: "d2" },
})
info := "subscription_count"
socketID := "1234.12"
client.TriggerBatch([]pusher.Event{
{ Channel: "donut-1", Name: "ev1", Data: "d1", SocketID: socketID, Info: &info },
{ Channel: "private-encrypted-secretdonut", Name: "ev2", Data: "d2", SocketID: socketID, Info: &info },
})
*/
func (c *Client) TriggerBatch(batch []Event) error {
func (c *Client) TriggerBatch(batch []Event) (*TriggerChannelsList, error) {
hasEncryptedChannel := false
// validate every channel name and every sockedID (if present) in batch
for _, event := range batch {
if !validChannel(event.Channel) {
return fmt.Errorf("The channel named %s has a non-valid name", event.Channel)
return nil, fmt.Errorf("The channel named %s has a non-valid name", event.Channel)
}
if err := validateSocketID(event.SocketID); err != nil {
return err
return nil, err
}
if isEncryptedChannel(event.Channel) {
hasEncryptedChannel = true
}
}
masterKey, keyErr := c.encryptionMasterKey()
if hasEncryptedChannel && keyErr != nil {
return keyErr
return nil, keyErr
}

payload, err := encodeTriggerBatchBody(batch, masterKey, c.OverrideMaxMessagePayloadKB)
if err != nil {
return err
return nil, err
}
path := fmt.Sprintf("/apps/%s/batch_events", c.AppID)
triggerURL, err := createRequestURL("POST", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, payload, nil, c.Cluster)
if err != nil {
return err
return nil, err
}
_, err = c.request("POST", triggerURL, payload)
return err
response, err := c.request("POST", triggerURL, payload)
if err != nil {
return nil, err
}

return unmarshalledTriggerChannelsList(response)
}

/*
Channels returns a list of all the channels in an application. The parameter
`additionalQueries` is a map with query options. A key with `"filter_by_prefix"`
will filter the returned channels. To get number of users subscribed to a
presence-channel, specify an `"info"` key with value `"user_count"`. Pass in
`nil` if you do not wish to specify any query attributes
channelsParams := map[string]string{
"filter_by_prefix": "presence-",
"info": "user_count",
}
ChannelsParams are any parameters than can be sent with a Channels request.
*/
type ChannelsParams struct {
// FilterByPrefix will filter the returned channels.
FilterByPrefix *string
// Info should be specified with a value of "user_count" to get number
// of users subscribed to a presence-channel. Pass in `nil` if you do
// not wish to specify any query attributes.
Info *string
}

channels, err := client.Channels(channelsParams)
func (parameters ChannelsParams) toMap() map[string]string {
m := make(map[string]string)
if parameters.FilterByPrefix != nil {
m["filter_by_prefix"] = *parameters.FilterByPrefix
}
if parameters.Info != nil {
m["info"] = *parameters.Info
}
return m
}

//channels=> &{Channels:map[presence-chatroom:{UserCount:4} presence-notifications:{UserCount:31} ]}
/*
Channels returns a list of all the channels in an application.
prefixFilter := "presence-"
attributes := "user_count"
parameters := ChannelsParams{FilterByPrefix: &prefixFilter, Info: &attributes}
channels, err := client.Channels(parameters)
//channels=> &{Channels:map[presence-chatroom:{UserCount:4} presence-notifications:{UserCount:31} ]}
*/
func (c *Client) Channels(additionalQueries map[string]string) (*ChannelsList, error) {
func (c *Client) Channels(parameters ChannelsParams) (*ChannelsList, error) {
path := fmt.Sprintf("/apps/%s/channels", c.AppID)
u, err := createRequestURL("GET", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, nil, additionalQueries, c.Cluster)
u, err := createRequestURL("GET", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, nil, parameters.toMap(), c.Cluster)
if err != nil {
return nil, err
}
Expand All @@ -295,25 +397,36 @@ func (c *Client) Channels(additionalQueries map[string]string) (*ChannelsList, e
}

/*
Channel allows you to get the state of a single channel. The parameter
`additionalQueries` is a map with query options. An `"info"` key can have
comma-separated vales of `"user_count"`, for presence-channels, and
`"subscription_count"`, for all-channels. Note that the subscription count is
not allowed by default. Please contact us at http://support.pusher.com if you
wish to enable this. Pass in `nil` if you do not wish to specify any query
attributes.
channelParams := map[string]string{
"info": "user_count,subscription_count",
}
ChannelParams are any parameters than can be sent with a Channel request.
*/
type ChannelParams struct {
// Info is comma-separated vales of `"user_count"`, for
// presence-channels, and `"subscription_count"`, for all-channels.
// Note that the subscription count is not allowed by default. Please
// contact us at http://support.pusher.com if you wish to enable this.
// Pass in `nil` if you do not wish to specify any query attributes.
Info *string
}

func (parameters ChannelParams) toMap() map[string]string {
m := make(map[string]string)
if parameters.Info != nil {
m["info"] = *parameters.Info
}
return m
}

/*
Channel allows you to get the state of a single channel.
channel, err := client.Channel("presence-chatroom", channelParams)
attributes := "user_count,subscription_count"
channel, err := client.Channel("presence-chatroom", &ChannelParams{Info: &attributes})
//channel=> &{Name:presence-chatroom Occupied:true UserCount:42 SubscriptionCount:42}
*/
func (c *Client) Channel(name string, additionalQueries map[string]string) (*Channel, error) {
func (c *Client) Channel(name string, parameters ChannelParams) (*Channel, error) {
path := fmt.Sprintf("/apps/%s/channels/%s", c.AppID, name)
u, err := createRequestURL("GET", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, nil, additionalQueries, c.Cluster)
u, err := createRequestURL("GET", c.Host, path, c.Key, c.Secret, authTimestamp(), c.Secure, nil, parameters.toMap(), c.Cluster)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 3838ff8

Please sign in to comment.